From bfc5a33ac4c0de9b09efa28dbc2a2f0a4a8e50d4 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 27 May 2014 15:57:51 +0200 Subject: [PATCH 001/487] Weighted_point type. --- .../CGAL/NewKernel_d/Types/Weighted_point.h | 76 +++++++++++++++++++ .../include/CGAL/NewKernel_d/functor_tags.h | 3 + NewKernel_d/test/NewKernel_d/Epick_d.cpp | 13 ++++ 3 files changed, 92 insertions(+) create mode 100644 NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h new file mode 100644 index 00000000000..020ee430a78 --- /dev/null +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -0,0 +1,76 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_TYPE_WP_H +#define CGAL_KD_TYPE_WP_H +#include +#include +namespace CGAL { +template class Weighted_point { + typedef typename Get_type::type FT_; + typedef typename Get_type::type Point_; + Point_ c_; + FT_ w_; + + public: + Weighted_point(Point_ const&p, FT_ const&w): c_(p), w_(w) {} + // TODO: Add a piecewise constructor? + + Point_ const& point()const{return c_;} + FT_ const& weight()const{return w_;} +}; + +namespace CartesianDKernelFunctors { +template struct Construct_weighted_point : Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Construct_weighted_point) + typedef typename Get_type::type result_type; + typedef typename Get_type::type Point; + typedef typename Get_type::type FT; + result_type operator()(Point const&a, FT const&b)const{ + return result_type(a,b); + } +}; + +template struct Point_drop_weight { + CGAL_FUNCTOR_INIT_IGNORE(Point_drop_weight) + typedef typename Get_type::type argument_type; + typedef typename Get_type::type const& result_type; + + result_type operator()(argument_type const&s)const{ + return s.point(); + } +}; + +template struct Point_weight { + CGAL_FUNCTOR_INIT_IGNORE(Point_weight) + typedef typename Get_type::type argument_type; + typedef typename Get_type::type const& result_type; + + result_type operator()(argument_type const&s)const{ + return s.weight(); + } +}; + +} +CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::Weighted_point),(Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(Weighted_point_tag,Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_drop_weight),(Weighted_point_tag,Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight),(Weighted_point_tag,Point_tag),()); +} // namespace CGAL +#endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index bc34a141e22..626bc56af04 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -156,6 +156,7 @@ namespace CGAL { DECL_OBJ(Iso_box, Object); DECL_OBJ(Bbox, Object); DECL_OBJ(Aff_transformation, Object); + DECL_OBJ(Weighted_point, Object); #undef DECL_OBJ_ #undef DECL_OBJ @@ -197,6 +198,7 @@ namespace CGAL { DECL_COMPUTE(Scalar_product); DECL_COMPUTE(Hyperplane_translation); DECL_COMPUTE(Value_at); + DECL_COMPUTE(Point_weight); #undef DECL_COMPUTE #define DECL_ITER_OBJ(X,Y,Z,C) struct X##_tag {}; \ @@ -246,6 +248,7 @@ namespace CGAL { DECL_CONSTRUCT(Translated_point,Point); DECL_CONSTRUCT(Point_to_vector,Vector); DECL_CONSTRUCT(Vector_to_point,Point); + DECL_CONSTRUCT(Point_drop_weight,Point); #undef DECL_CONSTRUCT #if 0 #define DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \ diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index aeea3b71a33..6f55b628f44 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -11,6 +11,7 @@ #include #include #include +#include templatevoid marc_use(){} #define USE_TYPE(T) marc_use() @@ -390,6 +391,7 @@ void test3(){ P x4=cp(0,0,1); P x5=cp(0,0,0); P x6=cp(0,0,-1); + assert(!ed(x1,x2)); P tab2[]={x1,x2,x3,x4,x5}; assert(po(tab2+0,tab2+4)==CGAL::POSITIVE); assert(sos(tab2+0,tab2+4,x5)==CGAL::ON_POSITIVE_SIDE); @@ -436,6 +438,17 @@ void test3(){ assert(ifsos(fozn, tz+0, tz+3, tz[4]) == CGAL::ON_NEGATIVE_SIDE); assert(ifsos(fozp, tz+0, tz+3, tz[5]) == CGAL::ON_NEGATIVE_SIDE); assert(ifsos(fozn, tz+0, tz+3, tz[5]) == CGAL::ON_POSITIVE_SIDE); + + typedef typename CGAL::Get_type::type WP; + typedef typename CGAL::Get_functor >::type CWP; + typedef typename CGAL::Get_functor::type PDW; + typedef typename CGAL::Get_functor::type PW; + CWP cwp (k); + PDW pdw (k); + PW pw (k); + WP wp = cwp (x1, 2); + assert (pw(wp) == 2); + assert (ed(pdw(wp), x1)); } template struct CGAL::Epick_d >; template struct CGAL::Epick_d >; From 8ac34ad7a630e4bd3f68068d892395b1e2c28bd8 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 28 May 2014 15:13:57 +0200 Subject: [PATCH 002/487] Re-introduce code removed in merge conflict. --- NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index 02798ad519f..40b73040213 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -175,6 +175,7 @@ namespace CGAL { CGAL_DECL_OBJ(Iso_box, Object); CGAL_DECL_OBJ(Bbox, Object); CGAL_DECL_OBJ(Aff_transformation, Object); + CGAL_DECL_OBJ(Weighted_point, Object); #undef CGAL_DECL_OBJ_ #undef CGAL_DECL_OBJ @@ -216,6 +217,7 @@ namespace CGAL { CGAL_DECL_COMPUTE(Scalar_product); CGAL_DECL_COMPUTE(Hyperplane_translation); CGAL_DECL_COMPUTE(Value_at); + CGAL_DECL_COMPUTE(Point_weight); #undef CGAL_DECL_COMPUTE #define CGAL_DECL_ITER_OBJ(X,Y,Z,C) struct X##_tag {}; \ @@ -265,6 +267,7 @@ namespace CGAL { CGAL_DECL_CONSTRUCT(Translated_point,Point); CGAL_DECL_CONSTRUCT(Point_to_vector,Vector); CGAL_DECL_CONSTRUCT(Vector_to_point,Point); + CGAL_DECL_CONSTRUCT(Point_drop_weight,Point); #undef CGAL_DECL_CONSTRUCT #if 0 #define CGAL_DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \ From a7417b582dfdc40c15b8172ddc37772b5e8535ba Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 28 May 2014 16:40:14 +0200 Subject: [PATCH 003/487] Power test. --- .../CGAL/NewKernel_d/Cartesian_LA_base.h | 1 + .../NewKernel_d/Kernel_object_converter.h | 12 ++ .../CGAL/NewKernel_d/Types/Weighted_point.h | 25 +++- .../CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h | 2 + .../NewKernel_d/Wrapper/Weighted_point_d.h | 129 ++++++++++++++++++ .../NewKernel_d/function_objects_cartesian.h | 54 ++++++++ .../include/CGAL/NewKernel_d/functor_tags.h | 2 + NewKernel_d/test/NewKernel_d/Epick_d.cpp | 4 + Number_types/include/CGAL/Gmpq.h | 11 ++ Number_types/include/CGAL/Interval_nt.h | 7 + 10 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_base.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_base.h index 28893d64830..80ee4b33580 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_base.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_base.h @@ -87,6 +87,7 @@ struct Cartesian_LA_base_d : public Dimension_base ::add::type ::add::type ::add::type + ::add::type Object_list; typedef typeset< Point_cartesian_const_iterator_tag>::type diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_object_converter.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_object_converter.h index b13303fa24c..36f0c687da4 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_object_converter.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_object_converter.h @@ -117,5 +117,17 @@ template struct KO_converter{ } }; +template struct KO_converter{ + typedef typename Get_type::type argument_type; + typedef typename Get_type::type result_type; + template + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& s) const { + typename Get_functor::type pdw(k1); + typename Get_functor::type pw(k1); + typename Get_functor >::type cwp(k2); + return cwp(conv(pdw(s)),conv(pw(s))); + } +}; + } #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 020ee430a78..553f2df6efe 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -50,7 +50,8 @@ template struct Construct_weighted_point : Store_kernel { template struct Point_drop_weight { CGAL_FUNCTOR_INIT_IGNORE(Point_drop_weight) typedef typename Get_type::type argument_type; - typedef typename Get_type::type const& result_type; + typedef typename Get_type::type result_type; + // Returning a reference would be too fragile result_type operator()(argument_type const&s)const{ return s.point(); @@ -60,17 +61,37 @@ template struct Point_drop_weight { template struct Point_weight { CGAL_FUNCTOR_INIT_IGNORE(Point_weight) typedef typename Get_type::type argument_type; - typedef typename Get_type::type const& result_type; + typedef typename Get_type::type result_type; result_type operator()(argument_type const&s)const{ return s.weight(); } }; +template struct Power_test : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_test) + typedef R_ R; + typedef typename Get_type::type result_type; + + template + result_type operator()(Iter const& f, Iter const& e, Pt const& p0) const { + typename Get_functor::type ptr(this->kernel()); + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + return ptr ( + make_transforming_iterator (f, pdw), + make_transforming_iterator (e, pdw), + make_transforming_iterator (f, pw), + pdw (p0), + pw (p0)); + } +}; + } CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::Weighted_point),(Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_drop_weight),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight),(Weighted_point_tag,Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Power_test_tag,(CartesianDKernelFunctors::Power_test),(Weighted_point_tag),(Power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); } // namespace CGAL #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h index a0c6d8f650c..520a96c8e9e 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -106,6 +107,7 @@ CGAL_REGISTER_OBJECT_WRAPPER(Vector); CGAL_REGISTER_OBJECT_WRAPPER(Segment); CGAL_REGISTER_OBJECT_WRAPPER(Sphere); CGAL_REGISTER_OBJECT_WRAPPER(Hyperplane); +CGAL_REGISTER_OBJECT_WRAPPER(Weighted_point); #undef CGAL_REGISTER_OBJECT_WRAPPER // Note: this tends to be an all or nothing thing currently, wrapping diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h new file mode 100644 index 00000000000..877eea21b0f --- /dev/null +++ b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h @@ -0,0 +1,129 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_WRAPPER_WEIGHTED_POINT_D_H +#define CGAL_WRAPPER_WEIGHTED_POINT_D_H + +#include +#include +#include +#include +#include +#ifndef CGAL_CXX11 +#include +#endif +#include + +namespace CGAL { +namespace Wrap { + +template +class Weighted_point_d : public Get_type::type +{ + typedef typename Get_type::type FT_; + typedef typename R_::Kernel_base Kbase; + typedef typename Get_type::type Point_; + typedef typename Get_functor >::type CWPBase; + typedef typename Get_functor::type PDWBase; + typedef typename Get_functor::type PWBase; + + typedef Weighted_point_d Self; + BOOST_STATIC_ASSERT((boost::is_same::type>::value)); + +public: + + typedef Tag_true Is_wrapper; + typedef typename R_::Default_ambient_dimension Ambient_dimension; + typedef Dimension_tag<0> Feature_dimension; + + typedef typename Get_type::type Rep; + + const Rep& rep() const + { + return *this; + } + + Rep& rep() + { + return *this; + } + + typedef R_ R; + +#ifdef CGAL_CXX11 + template::type...>,std::tuple >::value>::type> explicit Weighted_point_d(U&&...u) + : Rep(CWPBase()(std::forward(u)...)){} + +// // called from Construct_point_d +// template explicit Point_d(Eval_functor&&,U&&...u) +// : Rep(Eval_functor(), std::forward(u)...){} + template explicit Weighted_point_d(Eval_functor&&,F&&f,U&&...u) + : Rep(std::forward(f)(std::forward(u)...)){} + +#if 0 + // the new standard may make this necessary + Point_d(Point_d const&)=default; + Point_d(Point_d &);//=default; + Point_d(Point_d &&)=default; +#endif + + // try not to use these + Weighted_point_d(Rep const& v) : Rep(v) {} + Weighted_point_d(Rep& v) : Rep(static_cast(v)) {} + Weighted_point_d(Rep&& v) : Rep(std::move(v)) {} + +#else + + Weighted_point_d() : Rep(CWPBase()()) {} + + Weighted_point_d(Rep const& v) : Rep(v) {} // try not to use it + +#define CGAL_CODE(Z,N,_) template \ + explicit Weighted_point_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(CWPBase()( \ + BOOST_PP_ENUM_PARAMS(N,t))) {} \ + \ + template \ + Weighted_point_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {} + /* + template \ + Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {} + */ + + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + +#endif + + //TODO: use references? + Point_ point()const{ + return Point_(Eval_functor(),PDWBase(),rep()); + } + FT_ weight()const{ + return PWBase()(rep()); + } + +}; + +} //namespace Wrap +} //namespace CGAL + +#endif // CGAL_WRAPPER_SPHERE_D_H diff --git a/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h index e7e6be1bf1e..cb34a9fa377 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h @@ -529,6 +529,60 @@ template struct Orientation : private Store_kernel { } #endif +namespace CartesianDKernelFunctors { +template struct Power_test_raw : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_test_raw) + typedef R_ R; + typedef typename Get_type::type RT; + typedef typename Get_type::type FT; + typedef typename Get_type::type Point; + typedef typename Get_type::type result_type; + typedef typename Increment_dimension::type D1; + typedef typename Increment_dimension::type D2; + typedef typename R::LA::template Rebind_dimension::Other LA; + typedef typename LA::Square_matrix Matrix; + + template + result_type operator()(IterP f, IterP const& e, IterW fw, Pt const& p0, Wt const& w0) const { + typedef typename Get_functor::type Sqdo; + typename Get_functor::type c(this->kernel()); + typename Get_functor::type pd(this->kernel()); + + int d=pd(p0); + Matrix m(d+1,d+1); + if(CGAL::Is_stored::value) { + Sqdo sqdo(this->kernel()); + FT const& h0 = sqdo(p0) - w0; + for(int i=0;f!=e;++f,++fw,++i) { + Point const& p=*f; + for(int j=0;j),(Point_tag),(Point_dimension_tag,Squared_distance_to_origin_tag,Compute_point_cartesian_coordinate_tag)); + +// TODO: make Side_of_oriented_sphere call Power_test_raw namespace CartesianDKernelFunctors { template struct Side_of_oriented_sphere : private Store_kernel { CGAL_FUNCTOR_INIT_STORE(Side_of_oriented_sphere) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index 40b73040213..53a17530728 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -307,6 +307,8 @@ namespace CGAL { CGAL_DECL_PREDICATE(Affinely_independent); CGAL_DECL_PREDICATE(Contained_in_linear_hull); CGAL_DECL_PREDICATE(Contained_in_simplex); + CGAL_DECL_PREDICATE(Power_test_raw); + CGAL_DECL_PREDICATE(Power_test); #undef CGAL_DECL_PREDICATE #define CGAL_DECL_MISC(X) struct X##_tag {}; \ diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index fe36b903d11..1aae2c91ba7 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -520,12 +520,16 @@ void test3(){ typedef typename CGAL::Get_functor >::type CWP; typedef typename CGAL::Get_functor::type PDW; typedef typename CGAL::Get_functor::type PW; + typedef typename CGAL::Get_functor::type PT; CWP cwp (k); PDW pdw (k); PW pw (k); + PT pt (k); WP wp = cwp (x1, 2); assert (pw(wp) == 2); assert (ed(pdw(wp), x1)); + WP tabw[]={cwp(x1,0),cwp(x2,0),cwp(x3,0),cwp(x4,0),cwp(x5,0)}; + assert(pt(tabw+0,tabw+4,tabw[4])==CGAL::ON_POSITIVE_SIDE); } template struct CGAL::Epick_d >; template struct CGAL::Epick_d >; diff --git a/Number_types/include/CGAL/Gmpq.h b/Number_types/include/CGAL/Gmpq.h index 38fd09242c4..b17fbe2b546 100644 --- a/Number_types/include/CGAL/Gmpq.h +++ b/Number_types/include/CGAL/Gmpq.h @@ -155,6 +155,17 @@ namespace Eigen { MulCost = 100 }; }; + + namespace internal { + template<> + struct significant_decimals_impl + { + static inline int run() + { + return 0; + } + }; + } } //since types are included by Gmp_coercion_traits.h: diff --git a/Number_types/include/CGAL/Interval_nt.h b/Number_types/include/CGAL/Interval_nt.h index e725e74621e..7b84e600781 100644 --- a/Number_types/include/CGAL/Interval_nt.h +++ b/Number_types/include/CGAL/Interval_nt.h @@ -1283,6 +1283,13 @@ namespace Eigen { MulCost = 10 }; }; + + namespace internal { + template struct significant_decimals_impl; + template + struct significant_decimals_impl > + : significant_decimals_impl::value_type> { }; + } } #endif // CGAL_INTERVAL_NT_H From 66679e327d9afd25b02a2d6ddc2ef69deb1bd18e Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 28 May 2014 17:00:37 +0200 Subject: [PATCH 004/487] In_flat_power_test --- .../include/CGAL/NewKernel_d/Coaffine.h | 50 +++++++++++++++++++ .../CGAL/NewKernel_d/Types/Weighted_point.h | 21 ++++++++ .../include/CGAL/NewKernel_d/functor_tags.h | 2 + NewKernel_d/test/NewKernel_d/Epick_d.cpp | 4 ++ 4 files changed, 77 insertions(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h index 1c2efe462d8..c8f1950ce13 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h @@ -268,11 +268,61 @@ template struct In_flat_side_of_oriented_sphere : private Store_kernel } }; +template struct In_flat_power_test_raw : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(In_flat_power_test_raw) + typedef R_ R; + typedef typename Get_type::type FT; + typedef typename Get_type::type Point; + typedef typename Get_type::type result_type; + typedef typename Increment_dimension::type D1; + typedef typename Increment_dimension::type D2; + typedef typename R::LA::template Rebind_dimension::Other LA; + typedef typename LA::Square_matrix Matrix; + + template + result_type operator()(Flat_orientation const&o, Iter f, Iter e, IterW fw, Point const&x, Wt const&w) const { + // TODO: can't work in the projection, but we should at least remove the row of 1s. + typename Get_functor::type c(this->kernel()); + typename Get_functor::type pd(this->kernel()); + int d=pd(*f); + Matrix m(d+2,d+2); + int i=0; + for(;f!=e;++f,++fw,++i) { + Point const& p=*f; + m(i,0)=1; + m(i,d+1)=-*fw; + for(int j=0;j::const_iterator it = o.rest.begin(); it != o.rest.end() /* i),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); CGAL_KD_DEFAULT_FUNCTOR(In_flat_side_of_oriented_sphere_tag,(CartesianDKernelFunctors::In_flat_side_of_oriented_sphere),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); +CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_test_raw_tag,(CartesianDKernelFunctors::In_flat_power_test_raw),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); CGAL_KD_DEFAULT_FUNCTOR(Construct_flat_orientation_tag,(CartesianDKernelFunctors::Construct_flat_orientation),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag,In_flat_orientation_tag)); CGAL_KD_DEFAULT_FUNCTOR(Contained_in_affine_hull_tag,(CartesianDKernelFunctors::Contained_in_affine_hull),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); } diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 553f2df6efe..5619750f939 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -87,11 +87,32 @@ template struct Power_test : private Store_kernel { } }; +template struct In_flat_power_test : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(In_flat_power_test) + typedef R_ R; + typedef typename Get_type::type result_type; + + template + result_type operator()(Fo const& fo, Iter const& f, Iter const& e, Pt const& p0) const { + typename Get_functor::type ptr(this->kernel()); + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + return ptr ( + fo, + make_transforming_iterator (f, pdw), + make_transforming_iterator (e, pdw), + make_transforming_iterator (f, pw), + pdw (p0), + pw (p0)); + } +}; + } CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::Weighted_point),(Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_drop_weight),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Power_test_tag,(CartesianDKernelFunctors::Power_test),(Weighted_point_tag),(Power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_test_tag,(CartesianDKernelFunctors::In_flat_power_test),(Weighted_point_tag),(In_flat_power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); } // namespace CGAL #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index 53a17530728..20acd9a80cf 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -309,6 +309,8 @@ namespace CGAL { CGAL_DECL_PREDICATE(Contained_in_simplex); CGAL_DECL_PREDICATE(Power_test_raw); CGAL_DECL_PREDICATE(Power_test); + CGAL_DECL_PREDICATE(In_flat_power_test_raw); + CGAL_DECL_PREDICATE(In_flat_power_test); #undef CGAL_DECL_PREDICATE #define CGAL_DECL_MISC(X) struct X##_tag {}; \ diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 1aae2c91ba7..9714a03e2a2 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -521,15 +521,19 @@ void test3(){ typedef typename CGAL::Get_functor::type PDW; typedef typename CGAL::Get_functor::type PW; typedef typename CGAL::Get_functor::type PT; + typedef typename CGAL::Get_functor::type IFPT; CWP cwp (k); PDW pdw (k); PW pw (k); PT pt (k); + IFPT ifpt (k); WP wp = cwp (x1, 2); + WP xw6 = cwp (x6, 0); assert (pw(wp) == 2); assert (ed(pdw(wp), x1)); WP tabw[]={cwp(x1,0),cwp(x2,0),cwp(x3,0),cwp(x4,0),cwp(x5,0)}; assert(pt(tabw+0,tabw+4,tabw[4])==CGAL::ON_POSITIVE_SIDE); + assert(ifpt(fo4,tabw+0,tabw+3,xw6)==CGAL::ON_POSITIVE_SIDE); } template struct CGAL::Epick_d >; template struct CGAL::Epick_d >; From 1d2d456d1780263ffce9f117296f8f762ec0f47d Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 28 May 2014 17:17:35 +0200 Subject: [PATCH 005/487] Typedefs for the weighted_point interfaces. --- .../CGAL/NewKernel_d/Kernel_d_interface.h | 13 +++++++++++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 22 +++++++++---------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index af0438eb4a4..5d95346c1dc 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -54,6 +54,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_type::type Ray_d; typedef typename Get_type::type Iso_box_d; typedef typename Get_type::type Aff_transformation_d; + typedef typename Get_type::type Weighted_point_d; typedef typename Get_functor::type Compute_coordinate_d; typedef typename Get_functor::type Compare_lexicographically_d; typedef typename Get_functor::type Equal_d; @@ -64,10 +65,12 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Less_coordinate_d; typedef typename Get_functor::type Point_dimension_d; typedef typename Get_functor::type Side_of_oriented_sphere_d; + typedef typename Get_functor::type Power_test_d; typedef typename Get_functor::type Contained_in_affine_hull_d; typedef typename Get_functor::type Construct_flat_orientation_d; typedef typename Get_functor::type In_flat_orientation_d; typedef typename Get_functor::type In_flat_side_of_oriented_sphere_d; + typedef typename Get_functor::type In_flat_power_test_d; typedef typename Get_functor::type Point_to_vector_d; typedef typename Get_functor::type Vector_to_point_d; typedef typename Get_functor >::type Construct_point_d; @@ -80,6 +83,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor >::type Construct_ray_d; typedef typename Get_functor >::type Construct_iso_box_d; typedef typename Get_functor >::type Construct_aff_transformation_d; + typedef typename Get_functor >::type Construct_weighted_point_d; typedef typename Get_functor::type Midpoint_d; struct Component_accessor_d : private Store_kernel { typedef Kernel R_; // for the macro @@ -145,6 +149,9 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Orthogonal_vector_d; typedef typename Get_functor::type Linear_base_d; + typedef typename Get_functor::type Point_weight_d; + typedef typename Get_functor::type Point_drop_weight_d; + //TODO: //typedef ??? Intersect_d; @@ -161,6 +168,7 @@ template struct Kernel_d_interface : public Base_ { Point_dimension_d point_dimension_d_object()const{ return Point_dimension_d(*this); } Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); } Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } + Power_test_d power_test_d_object()const{ return Power_test_d(*this); } Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); } Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); } @@ -168,6 +176,7 @@ template struct Kernel_d_interface : public Base_ { Construct_flat_orientation_d construct_flat_orientation_d_object()const{ return Construct_flat_orientation_d(*this); } In_flat_orientation_d in_flat_orientation_d_object()const{ return In_flat_orientation_d(*this); } In_flat_side_of_oriented_sphere_d in_flat_side_of_oriented_sphere_d_object()const{ return In_flat_side_of_oriented_sphere_d(*this); } + In_flat_power_test_d in_flat_power_test_d_object()const{ return In_flat_power_test_d(*this); } Point_to_vector_d point_to_vector_d_object()const{ return Point_to_vector_d(*this); } Vector_to_point_d vector_to_point_d_object()const{ return Vector_to_point_d(*this); } Affine_rank_d affine_rank_d_object()const{ return Affine_rank_d(*this); } @@ -193,6 +202,10 @@ template struct Kernel_d_interface : public Base_ { Construct_ray_d construct_ray_d_object()const{ return Construct_ray_d(*this); } Construct_iso_box_d construct_iso_box_d_object()const{ return Construct_iso_box_d(*this); } Construct_aff_transformation_d construct_aff_transformation_d_object()const{ return Construct_aff_transformation_d(*this); } + Construct_weighted_point_d construct_weighted_point_d_object()const{ return Construct_weighted_point_d(*this); } + + Point_weight_d point_weight_d_object()const{ return Point_weight_d(*this); } + Point_drop_weight_d point_drop_weight_d_object()const{ return Point_drop_weight_d(*this); } // Dummies for those required functors missing a concept. typedef Null_functor Position_on_line_d; diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 9714a03e2a2..578e190dd80 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -516,17 +516,17 @@ void test3(){ assert(ifsos(fozp, tz+0, tz+3, tz[5]) == CGAL::ON_NEGATIVE_SIDE); assert(ifsos(fozn, tz+0, tz+3, tz[5]) == CGAL::ON_POSITIVE_SIDE); - typedef typename CGAL::Get_type::type WP; - typedef typename CGAL::Get_functor >::type CWP; - typedef typename CGAL::Get_functor::type PDW; - typedef typename CGAL::Get_functor::type PW; - typedef typename CGAL::Get_functor::type PT; - typedef typename CGAL::Get_functor::type IFPT; - CWP cwp (k); - PDW pdw (k); - PW pw (k); - PT pt (k); - IFPT ifpt (k); + typedef typename K1::Weighted_point_d WP; + typedef typename K1::Construct_weighted_point_d CWP; + typedef typename K1::Point_drop_weight_d PDW; + typedef typename K1::Point_weight_d PW; + typedef typename K1::Power_test_d PT; + typedef typename K1::In_flat_power_test_d IFPT; + CWP cwp Kinit(construct_weighted_point_d_object); + PDW pdw Kinit(point_drop_weight_d_object); + PW pw Kinit(point_weight_d_object); + PT pt Kinit(power_test_d_object); + IFPT ifpt Kinit(in_flat_power_test_d_object); WP wp = cwp (x1, 2); WP xw6 = cwp (x6, 0); assert (pw(wp) == 2); From df37199c1efbf0aedfbdcbb179b5083ab7f27bc0 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 6 Jun 2014 17:24:41 +0200 Subject: [PATCH 006/487] Include Weighted_point.h in Epick_d.h, for now. --- NewKernel_d/include/CGAL/Epick_d.h | 1 + 1 file changed, 1 insertion(+) diff --git a/NewKernel_d/include/CGAL/Epick_d.h b/NewKernel_d/include/CGAL/Epick_d.h index cf780630c56..6443853994f 100644 --- a/NewKernel_d/include/CGAL/Epick_d.h +++ b/NewKernel_d/include/CGAL/Epick_d.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace CGAL { From 53d0db3e48ffc0f2275b400d25dcc8766455869c Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 6 Jun 2014 18:13:23 +0200 Subject: [PATCH 007/487] Move Weighted_point to a subnamespace to avoid collisions. All the good names are already taken ;-) --- NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 5619750f939..5d5f1c6301c 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -22,6 +22,7 @@ #include #include namespace CGAL { +namespace KerD { template class Weighted_point { typedef typename Get_type::type FT_; typedef typename Get_type::type Point_; @@ -35,6 +36,7 @@ template class Weighted_point { Point_ const& point()const{return c_;} FT_ const& weight()const{return w_;} }; +} namespace CartesianDKernelFunctors { template struct Construct_weighted_point : Store_kernel { @@ -108,7 +110,7 @@ template struct In_flat_power_test : private Store_kernel { }; } -CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::Weighted_point),(Point_tag),()); +CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::KerD::Weighted_point),(Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_drop_weight),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight),(Weighted_point_tag,Point_tag),()); From 43aba792977b7e02722b730aa2591b6ad9a46270 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 6 Jun 2014 23:00:52 +0200 Subject: [PATCH 008/487] Default constructor for Weighted_point_d. --- NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h | 5 +++++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 5d5f1c6301c..47593a3990e 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -47,6 +47,11 @@ template struct Construct_weighted_point : Store_kernel { result_type operator()(Point const&a, FT const&b)const{ return result_type(a,b); } + // Not really needed + result_type operator()()const{ + typename Get_functor >::type cp(this->kernel()); + return result_type(cp(),0); + } }; template struct Point_drop_weight { diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 578e190dd80..94cd23a14e3 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -527,7 +527,8 @@ void test3(){ PW pw Kinit(point_weight_d_object); PT pt Kinit(power_test_d_object); IFPT ifpt Kinit(in_flat_power_test_d_object); - WP wp = cwp (x1, 2); + WP wp; + wp = cwp (x1, 2); WP xw6 = cwp (x6, 0); assert (pw(wp) == 2); assert (ed(pdw(wp), x1)); From f88bfc0e51e4b8610914a0b13e798c63f919a615 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 11 Jun 2014 19:17:36 +0200 Subject: [PATCH 009/487] Work around Visual Studio's inability to perform the empty base optimization. (cherry picked from commit 0796b53a9193e983d8c4e2f7f13abdb0d89725ac) --- .../include/CGAL/NewKernel_d/Cartesian_filter_K.h | 7 +++++++ NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h | 12 ++++++++---- NewKernel_d/test/NewKernel_d/Makefile | 6 ++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 3f9804fecbe..403a0e4d68c 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace CGAL { @@ -45,6 +46,12 @@ struct Cartesian_filter_K : public Base_, typedef typename Store_kernel2::reference2_type EK_rt; EK_rt exact_kernel()const{return this->kernel2();} + // MSVC is too dumb to perform the empty base optimization. + typedef boost::mpl::and_< + internal::Do_not_store_kernel, + internal::Do_not_store_kernel, + internal::Do_not_store_kernel > Do_not_store_kernel; + //TODO: C2A/C2E could be able to convert *this into this->kernel() or this->kernel2(). typedef KernelD_converter C2A; typedef KernelD_converter C2E; diff --git a/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h b/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h index e888ae9eff3..253e12823f3 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h @@ -26,17 +26,21 @@ namespace CGAL { namespace internal { BOOST_MPL_HAS_XXX_TRAIT_DEF(Do_not_store_kernel) -template::value> struct Do_not_store_kernel { +template::value,bool=has_Do_not_store_kernel::value> struct Do_not_store_kernel { enum { value=false }; typedef Tag_false type; }; -template struct Do_not_store_kernel { +template struct Do_not_store_kernel { + enum { value=true }; + typedef Tag_true type; +}; +template struct Do_not_store_kernel { typedef typename T::Do_not_store_kernel type; enum { value=type::value }; }; } -template::value||internal::Do_not_store_kernel::value> +template::value> struct Store_kernel { Store_kernel(){} Store_kernel(R_ const&){} @@ -63,7 +67,7 @@ struct Store_kernel { }; //For a second kernel. TODO: find something more elegant -template::value||internal::Do_not_store_kernel::value> +template::value> struct Store_kernel2 { Store_kernel2(){} Store_kernel2(R_ const&){} diff --git a/NewKernel_d/test/NewKernel_d/Makefile b/NewKernel_d/test/NewKernel_d/Makefile index 55da4b935e6..1399658c7e6 100644 --- a/NewKernel_d/test/NewKernel_d/Makefile +++ b/NewKernel_d/test/NewKernel_d/Makefile @@ -1,15 +1,17 @@ all: normal cxx11 +CXX = g++ + CGAL_INC = -I. -I../../include -I../../../Algebraic_foundations/include -I../../../STL_Extension/include -I../../../Number_types/include -I../../../Kernel_23/include -I../../../Installation/include -DCGAL_DISABLE_ROUNDING_MATH_CHECK EIGEN_INC = `pkg-config --cflags eigen3|sed -e 's/-I/-isystem/g'` -DCGAL_EIGEN3_ENABLED normal: - g++ Epick_d.cpp -O2 -lCGAL -lboost_thread -frounding-math -Wall -Wextra -lmpfr -lgmp ${CGAL_INC} ${EIGEN_INC} + ${CXX} Epick_d.cpp -O2 -lCGAL -lboost_thread -frounding-math -Wall -Wextra -lmpfr -lgmp ${CGAL_INC} ${EIGEN_INC} ./a.out cxx11: - g++ -std=c++0x -O2 Epick_d.cpp -lCGAL -lboost_thread -frounding-math -Wall -Wextra -lmpfr -lgmp ${CGAL_INC} ${EIGEN_INC} -o b.out + ${CXX} -std=c++0x -O2 Epick_d.cpp -lCGAL -lboost_thread -frounding-math -Wall -Wextra -lmpfr -lgmp ${CGAL_INC} ${EIGEN_INC} -o b.out ./b.out #-DBOOST_RESULT_OF_USE_DECLTYPE From 54a3641ae7f0518cb5ba82349011aec71b8730de Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 12 Jun 2014 13:54:29 +0200 Subject: [PATCH 010/487] Regular_triangulation. Compiles but does not work. --- .../CGAL/NewKernel_d/KernelD_converter.h | 12 + .../include/CGAL/Delaunay_triangulation.h | 66 +- .../include/CGAL/Regular_triangulation.h | 880 +++++++++++++++++- .../Regular_triangulation_euclidean_traits.h | 206 ++++ Triangulation/include/CGAL/Triangulation.h | 50 +- .../CGAL/internal/Triangulation/utilities.h | 6 +- Triangulation/test/Triangulation/regular.cpp | 133 +++ 7 files changed, 1273 insertions(+), 80 deletions(-) create mode 100644 Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h create mode 100644 Triangulation/test/Triangulation/regular.cpp diff --git a/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h b/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h index 0fedf15a475..bb56e8648da 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h @@ -93,6 +93,15 @@ class KernelD_converter_ //typedef typename KOC::argument_type K1_Obj; //typedef typename KOC::result_type K2_Obj; public: + void disp(const std::array &o) const // CJTODO DEBUG + { + std::cerr << o[0]; + } + template + void disp(const P &o) const // CJTODO DEBUG + { + std::cerr << o.point()[0] ; + } using Base::operator(); // don't use directly, just make it accessible to the next level K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD true_type)const{ return KOC()(this->myself().kernel(),this->myself().kernel2(),this->myself(),o); @@ -101,6 +110,9 @@ class KernelD_converter_ return K1_Conv(this->myself().kernel())(this->myself().kernel2(),this->myself(),o); } K2_Obj operator()(argument_type const& o)const{ + std::cerr << "KernelD_converter_::operator() "; // CJTODO DEBUG + disp(o); + std::cerr << std::endl; return helper(o,no_converter()); } template struct result:Base::template result{}; diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 4bed54a75c7..78dd0e06d01 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -53,7 +53,7 @@ class Delaunay_triangulation public: // PUBLIC NESTED TYPES typedef DCTraits Geom_traits; - typedef typename Base::Triangulation_ds Triangulation_ds; + typedef typename Base::Triangulation_ds Triangulation_ds; typedef typename Base::Vertex Vertex; typedef typename Base::Full_cell Full_cell; @@ -69,16 +69,19 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Vertex_const_handle Vertex_const_handle; typedef typename Base::Vertex_const_iterator Vertex_const_iterator; - typedef typename Base::Full_cell_handle Full_cell_handle; - typedef typename Base::Full_cell_iterator Full_cell_iterator; - typedef typename Base::Full_cell_const_handle Full_cell_const_handle; - typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename Base::Full_cell_handle Full_cell_handle; + typedef typename Base::Full_cell_iterator Full_cell_iterator; + typedef typename Base::Full_cell_const_handle Full_cell_const_handle; + typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; typedef typename Base::size_type size_type; typedef typename Base::difference_type difference_type; typedef typename Base::Locate_type Locate_type; + //Tag to distinguish triangulations with weighted_points + typedef Tag_false Weighted_tag; + protected: // DATA MEMBERS @@ -93,6 +96,8 @@ public: //using Base::incident_full_cells; using Base::geom_traits; using Base::index_of_covertex; + using Base::index_of_second_covertex; + using Base::rotate_rotor; using Base::infinite_vertex; using Base::insert_in_hole; using Base::insert_outside_convex_hull_1; @@ -140,32 +145,6 @@ private: } }; public: - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UTILITIES - - // A co-dimension 2 sub-simplex. called a Rotor because we can rotate - // the two "covertices" around the sub-simplex. Useful for traversing the - // boundary of a hole. NOT DOCUMENTED - typedef cpp11::tuple Rotor; - Full_cell_handle full_cell(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<0>(r); - } - int index_of_covertex(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<1>(r); - } - int index_of_second_covertex(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<2>(r); - } - Rotor rotate_rotor(Rotor & r) // NOT DOCUMENTED... - { - int opposite = full_cell(r)->mirror_index(index_of_covertex(r)); - Full_cell_handle s = full_cell(r)->neighbor(index_of_covertex(r)); - int new_second = s->index(full_cell(r)->vertex(index_of_second_covertex(r))); - return Rotor(s, new_second, opposite); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS @@ -350,27 +329,6 @@ private: Conflict_traversal_pred_in_subspace; typedef Conflict_traversal_predicate Conflict_traversal_pred_in_fullspace; - - // This is used in the |remove(v)| member function to manage sets of Full_cell_handles - template< typename FCH > - struct Full_cell_set : public std::vector - { - typedef std::vector Base_set; - using Base_set::begin; - using Base_set::end; - void make_searchable() - { // sort the full cell handles - std::sort(begin(), end()); - } - bool contains(const FCH & fch) const - { - return std::binary_search(begin(), end(), fch); - } - bool contains_1st_and_not_2nd(const FCH & fst, const FCH & snd) const - { - return ( ! contains(snd) ) && ( contains(fst) ); - } - }; }; // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = @@ -425,7 +383,7 @@ Delaunay_triangulation // THE CASE cur_dim >= 2 // Gather the finite vertices sharing an edge with |v| - typedef Full_cell_set Simplices; + typedef Base::Full_cell_set Simplices; Simplices simps; std::back_insert_iterator out(simps); tds().incident_full_cells(v, out); @@ -561,7 +519,7 @@ Delaunay_triangulation Dark_s_handle dark_ret_s = dark_s; Full_cell_handle ret_s; - typedef Full_cell_set Dark_full_cells; + typedef Base::Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 2a1a3b49377..3e271b13998 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -1,8 +1,10 @@ -// Copyright (c) 2009 INRIA Sophia-Antipolis (France), +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. // -// This file is part of CGAL (www.cgal.org); you may redistribute it under -// the terms of the Q Public License version 1.0. -// See the file LICENSE.QPL distributed with CGAL. +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. @@ -13,7 +15,7 @@ // $URL$ // $Id$ // -// Author(s) : Samuel Hornus +// Author(s) : Clement Jamin #ifndef CGAL_REGULAR_TRIANGULATION_H #define CGAL_REGULAR_TRIANGULATION_H @@ -26,26 +28,860 @@ namespace CGAL { template< typename RTTraits, typename TDS_ = Default > class Regular_triangulation -: public Triangulation::type, - Triangulation_vertex, - Triangulation_full_cell > - >::type > +: public Triangulation< + RTTraits, + typename Default::Get, + Triangulation_full_cell > + >::type > { - typedef typename Maximal_dimension::type - Maximal_dimension_; - typedef typename Default::Get, - Triangulation_full_cell > - >::type TDS; - typedef Triangulation Base; - typedef Regular_triangulation Self; + typedef typename RTTraits::Dimension Maximal_dimension_; + typedef typename Default::Get< + TDS_, + Triangulation_data_structure< + Maximal_dimension_, + Triangulation_vertex, + Triangulation_full_cell + > >::type TDS; + typedef Triangulation Base; + typedef Regular_triangulation Self; + + typedef typename RTTraits::Orientation_d Orientation_d; + typedef typename RTTraits::Construct_weighted_point_d Construct_weighted_point_d; + typedef typename RTTraits::Power_test_d Power_test_d; + typedef typename RTTraits::In_flat_power_test_d In_flat_power_test_d; + typedef typename RTTraits::Flat_orientation_d Flat_orientation_d; + typedef typename RTTraits::Construct_flat_orientation_d Construct_flat_orientation_d; + typedef typename RTTraits::In_flat_orientation_d In_flat_orientation_d; + +public: // PUBLIC NESTED TYPES + + typedef RTTraits Geom_traits; + typedef typename Base::Triangulation_ds Triangulation_ds; + + typedef typename Base::Vertex Vertex; + typedef typename Base::Full_cell Full_cell; + typedef typename Base::Facet Facet; + typedef typename Base::Face Face; + + typedef Maximal_dimension_ Maximal_dimension; + typedef typename RTTraits::Bare_point Bare_point; + typedef typename RTTraits::Weighted_point Weighted_point; + + typedef typename Base::Vertex_handle Vertex_handle; + typedef typename Base::Vertex_iterator Vertex_iterator; + typedef typename Base::Vertex_const_handle Vertex_const_handle; + typedef typename Base::Vertex_const_iterator Vertex_const_iterator; + + typedef typename Base::Full_cell_handle Full_cell_handle; + typedef typename Base::Full_cell_iterator Full_cell_iterator; + typedef typename Base::Full_cell_const_handle Full_cell_const_handle; + typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + + typedef typename Base::size_type size_type; + typedef typename Base::difference_type difference_type; + + typedef typename Base::Locate_type Locate_type; + + //Tag to distinguish Delaunay from Regular triangulations + typedef Tag_true Weighted_tag; + +protected: // DATA MEMBERS + public: - typedef Maximal_dimension_ Maximal_dimension; -}; + + using Base::maximal_dimension; + using Base::are_incident_full_cells_valid; + using Base::coaffine_orientation_predicate; + using Base::reset_flat_orientation; + using Base::current_dimension; + using Base::geom_traits; + using Base::index_of_covertex; + using Base::infinite_vertex; + using Base::insert_in_hole; + using Base::insert_outside_convex_hull_1; + using Base::is_infinite; + using Base::is_valid; + using Base::locate; + using Base::points_begin; + using Base::set_neighbors; + using Base::new_full_cell; + using Base::number_of_vertices; + using Base::orientation; + using Base::tds; + using Base::reorient_full_cells; + using Base::full_cell; + using Base::full_cells_begin; + using Base::full_cells_end; + using Base::vertices_begin; + using Base::vertices_end; + +private: + //*** Power_test_in_flat_d *** CJTODO: better name? + typedef typename Base::Flat_orientation_d Flat_orientation_d; + typedef typename Base::Construct_flat_orientation_d Construct_flat_orientation_d; + typedef typename RTTraits::In_flat_power_test_d In_flat_power_test_d; + // Wrapper + struct Power_test_in_flat_d + { + boost::optional* fop; + Construct_flat_orientation_d cfo; + In_flat_power_test_d ifpt; + + Power_test_in_flat_d( + boost::optional& x, + Construct_flat_orientation_d const&y, + In_flat_power_test_d const&z) + : fop(&x), cfo(y), ifpt(z) {} + + template + CGAL::Orientation operator()(Iter a, Iter b, const Weighted_point & p)const + { + if(!*fop) + *fop=cfo(a,b); + return ifpt(fop->get(),a,b,p); + } + }; +public: + +// - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS + + Regular_triangulation(int dim, const Geom_traits k = Geom_traits()) + : Base(dim, k) + { + } + + // With this constructor, + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // It it used by the dark triangulations created by DT::remove + Regular_triangulation( + int dim, + const std::pair &preset_flat_orientation, + const Geom_traits k = Geom_traits()) + : Base(dim, preset_flat_orientation, k) + { + } + + ~Regular_triangulation() {} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS + + // Not Documented + Power_test_in_flat_d power_test_in_flat_predicate() const + { + return Power_test_in_flat_d ( + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), + geom_traits().in_flat_power_test_d_object() + ); + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + + Full_cell_handle remove(Vertex_handle); + Full_cell_handle remove(const Weighted_point & p, Full_cell_handle hint = Full_cell_handle()) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, hint); + if( Base::ON_VERTEX == lt ) + { + return remove(s->vertex(f.index(0))); + } + return Full_cell_handle(); + } + + template< typename ForwardIterator > + void remove(ForwardIterator start, ForwardIterator end) + { + while( start != end ) + remove(*start++); + } + + // Not documented + void remove_decrease_dimension(Vertex_handle); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS + + template< typename ForwardIterator > + size_type insert(ForwardIterator start, ForwardIterator end) + { + size_type n = number_of_vertices(); + typedef std::vector WP_vec; + WP_vec points(start, end); + Geom_traits::Point_drop_weight_d pdw = + geom_traits().point_drop_weight_d_object(); + spatial_sort( + boost::make_transform_iterator(points.begin(), pdw), + boost::make_transform_iterator(points.end(), pdw), + Geom_traits::Base()); + //spatial_sort(points.begin(), points.end(), geom_traits()); // CJTODO TEMP A REMETTRE + //spatial_sort(points.begin(), points.end(), Geom_traits::Base()); + Full_cell_handle hint; + for(WP_vec::const_iterator p = points.begin(); p != points.end(); ++p ) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle c = locate (*p, lt, f, ft, hint); + Vertex_handle v = insert (*p, lt, f, ft, c); + + hint = v == Vertex_handle() ? c : v->full_cell(); + } + return number_of_vertices() - n; + } + + Vertex_handle insert(const Weighted_point &, + const Locate_type, + const Face &, + const Facet &, + const Full_cell_handle); + + Vertex_handle insert(const Weighted_point & p, + const Full_cell_handle start = Full_cell_handle()) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, start); + return insert(p, lt, f, ft, s); + } + + Vertex_handle insert(const Weighted_point & p, const Vertex_handle hint) + { + CGAL_assertion( Vertex_handle() != hint ); + return insert(p, hint->full_cell()); + } + + Vertex_handle insert_outside_affine_hull(const Weighted_point &); + Vertex_handle insert_in_conflicting_cell(const Weighted_point &, const Full_cell_handle); + +// - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES + + bool is_in_conflict(const Weighted_point &, Full_cell_const_handle) const; + + template< class OrientationPredicate > + Oriented_side perturbed_power_test(const Weighted_point &, + Full_cell_const_handle, const OrientationPredicate &) const; + + template< typename OutputIterator > + Facet compute_conflict_zone(const Weighted_point &, const Full_cell_handle, OutputIterator) const; + + template < typename OrientationPredicate, typename PowerTestPredicate > + class Conflict_predicate + { + const Self & rt_; + const Weighted_point & p_; + OrientationPredicate ori_; + PowerTestPredicate power_test_; + int cur_dim_; + public: + Conflict_predicate( + const Self & rt, + const Weighted_point & p, + const OrientationPredicate & ori, + const PowerTestPredicate & power_test) + : rt_(rt), p_(p), ori_(ori), power_test_(power_test), cur_dim_(rt.current_dimension()) {} + + inline + bool operator()(Full_cell_const_handle s) const + { + bool ok; + if( ! rt_.is_infinite(s) ) + { + Oriented_side power_test = power_test_(rt_.points_begin(s), rt_.points_begin(s) + cur_dim_ + 1, p_); + if( ON_POSITIVE_SIDE == power_test ) + ok = true; + else if( ON_NEGATIVE_SIDE == power_test ) + ok = false; + else + ok = ON_POSITIVE_SIDE == rt_.perturbed_power_test(p_, s, ori_); + } + else + { + typedef typename Full_cell::Vertex_handle_const_iterator VHCI; + typedef Substitute_point_in_vertex_iterator F; + F spivi(rt_.infinite_vertex(), &p_); + + Orientation o = ori_( + boost::make_transform_iterator(s->vertices_begin(), spivi), + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + spivi)); + + if( POSITIVE == o ) + ok = true; + else if( o == NEGATIVE ) + ok = false; + else + ok = (*this)(s->neighbor( s->index( rt_.infinite_vertex() ) )); + } + return ok; + } + }; + + template < typename ConflictPredicate > + class Conflict_traversal_predicate + { + const Self & rt_; + const ConflictPredicate & pred_; + public: + Conflict_traversal_predicate(const Self & rt, const ConflictPredicate & pred) + : rt_(rt), pred_(pred) + {} + inline + bool operator()(const Facet & f) const + { + return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f))); + } + }; + +private: + // Some internal types to shorten notation + using typename Base::Coaffine_orientation_d; + using Base::flat_orientation_; + typedef Conflict_predicate + Conflict_pred_in_subspace; + typedef Conflict_predicate + Conflict_pred_in_fullspace; + typedef Conflict_traversal_predicate + Conflict_traversal_pred_in_subspace; + typedef Conflict_traversal_predicate + Conflict_traversal_pred_in_fullspace; +}; // class Regular_triangulation + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// FUNCTIONS THAT ARE MEMBER METHODS: + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + +template< typename RTTraits, typename TDS > +typename Regular_triangulation::Full_cell_handle +Regular_triangulation +::remove( Vertex_handle v ) +{ + CGAL_precondition( ! is_infinite(v) ); + CGAL_expensive_precondition( is_vertex(v) ); + + // THE CASE cur_dim == 0 + if( 0 == current_dimension() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + else if( 1 == current_dimension() ) + { // THE CASE cur_dim == 1 + if( 2 == number_of_vertices() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + Full_cell_handle left = v->full_cell(); + if( is_infinite(left) && left->neighbor(0)->index(left) == 0 ) // we are on the infinite right. + left = left->neighbor(0); + if( 0 == left->index(v) ) + left = left->neighbor(1); + CGAL_assertion( 1 == left->index(v) ); + Full_cell_handle right = left->neighbor(0); + if( ! is_infinite(right) ) + { + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); + } + else + { + tds().associate_vertex_with_full_cell(left, 1, left->vertex(0)); + tds().associate_vertex_with_full_cell(left, 0, infinite_vertex()); + set_neighbors(left, 0, left->neighbor(1), left->mirror_index(1)); + set_neighbors(left, 1, right->neighbor(1), right->mirror_index(1)); + } + tds().delete_vertex(v); + tds().delete_full_cell(right); + return left; + } + + // THE CASE cur_dim >= 2 + // Gather the finite vertices sharing an edge with |v| + typedef Base::Full_cell_set Simplices; + Simplices simps; + std::back_insert_iterator out(simps); + tds().incident_full_cells(v, out); + typedef std::set Vertex_set; + Vertex_set verts; + Vertex_handle vh; + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + for( int i = 0; i <= current_dimension(); ++i ) + { + vh = (*it)->vertex(i); + if( is_infinite(vh) ) + continue; + if( vh == v ) + continue; + verts.insert(vh); + } + + // After gathering finite neighboring vertices, create their Dark Delaunay triangulation + typedef Triangulation_vertex Dark_vertex_base; + typedef Triangulation_full_cell< + Geom_traits, + internal::Triangulation::Dark_full_cell_data > Dark_full_cell_base; + typedef Triangulation_data_structure Dark_tds; + typedef Regular_triangulation Dark_triangulation; + typedef typename Dark_triangulation::Face Dark_face; + typedef typename Dark_triangulation::Facet Dark_facet; + typedef typename Dark_triangulation::Vertex_handle Dark_v_handle; + typedef typename Dark_triangulation::Full_cell_handle Dark_s_handle; + + // If flat_orientation_ is defined, we give it the Dark triangulation + // so that the orientation it uses for "current_dimension()"-simplices is + // coherent with the global triangulation + Dark_triangulation dark_side( + maximal_dimension(), + flat_orientation_ ? + std::pair(current_dimension(), flat_orientation_.get_ptr()) + : std::pair(std::numeric_limits::max(), NULL) ); + + Dark_s_handle dark_s; + Dark_v_handle dark_v; + typedef std::map Vertex_map; + Vertex_map light_to_dark; + typename Vertex_set::iterator vit = verts.begin(); + while( vit != verts.end() ) + { + dark_v = dark_side.insert((*vit)->point(), dark_s); + dark_s = dark_v->full_cell(); + dark_v->data() = *vit; + light_to_dark[*vit] = dark_v; + ++vit; + } + + if( dark_side.current_dimension() != current_dimension() ) + { + CGAL_assertion( dark_side.current_dimension() + 1 == current_dimension() ); + // Here, the finite neighbors of |v| span a affine subspace of + // dimension one less than the current dimension. Two cases are possible: + if( (size_type)(verts.size() + 1) == number_of_vertices() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + else + { // |v| is strictly outside the convex hull of the rest of the points. This is an + // easy case: first, modify the finite full_cells, then, delete the infinite ones. + // We don't even need the Dark triangulation. + Simplices infinite_simps; + { + Simplices finite_simps; + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + if( is_infinite(*it) ) + infinite_simps.push_back(*it); + else + finite_simps.push_back(*it); + simps.swap(finite_simps); + } // now, simps only contains finite simplices + // First, modify the finite full_cells: + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + { + int v_idx = (*it)->index(v); + tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); + if( v_idx != 0 ) + { + // we must put the infinite vertex at index 0. + // OK, now with the new convention that the infinite vertex + // does not have to be at index 0, this is not necessary, + // but still, I prefer to keep this piece of code here. [-- Samuel Hornus] + (*it)->swap_vertices(0, v_idx); + // Now, we preserve the positive orientation of the full_cell + (*it)->swap_vertices(current_dimension() - 1, current_dimension()); + } + } + // Make the handles to infinite full cells searchable + infinite_simps.make_searchable(); + // Then, modify the neighboring relation + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + { + for( int i = 1; i <= current_dimension(); ++i ) + { + (*it)->vertex(i)->set_full_cell(*it); + Full_cell_handle n = (*it)->neighbor(i); + // Was |n| a finite full cell prior to removing |v| ? + if( ! infinite_simps.contains(n) ) + continue; + int n_idx = n->index(v); + set_neighbors(*it, i, n->neighbor(n_idx), n->neighbor(n_idx)->index(n)); + } + } + Full_cell_handle ret_s; + // Then, we delete the infinite full_cells + for( typename Simplices::iterator it = infinite_simps.begin(); it != infinite_simps.end(); ++it ) + tds().delete_full_cell(*it); + tds().delete_vertex(v); + return simps.front(); + } + } + else // From here on, dark_side.current_dimension() == current_dimension() + { + dark_side.infinite_vertex()->data() = infinite_vertex(); + light_to_dark[infinite_vertex()] = dark_side.infinite_vertex(); + } + + // Now, compute the conflict zone of v->point() in + // the dark side. This is precisely the set of full_cells + // that we have to glue back into the light side. + Dark_face dark_f(dark_side.maximal_dimension()); + Dark_facet dark_ft; + typename Dark_triangulation::Locate_type lt; + dark_s = dark_side.locate(v->point(), lt, dark_f, dark_ft); + CGAL_assertion( lt != Dark_triangulation::ON_VERTEX + && lt != Dark_triangulation::OUTSIDE_AFFINE_HULL ); + + // |ret_s| is the full_cell that we return + Dark_s_handle dark_ret_s = dark_s; + Full_cell_handle ret_s; + + typedef Base::Full_cell_set Dark_full_cells; + Dark_full_cells conflict_zone; + std::back_insert_iterator dark_out(conflict_zone); + + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); + // Make the dark simplices in the conflict zone searchable + conflict_zone.make_searchable(); + + // THE FOLLOWING SHOULD MAYBE GO IN TDS. + // Here is the plan: + // 1. Pick any Facet from boundary of the light zone + // 2. Find corresponding Facet on boundary of dark zone + // 3. stitch. + + // 1. Build a facet on the boudary of the light zone: + Full_cell_handle light_s = *simps.begin(); + Facet light_ft(light_s, light_s->index(v)); + + // 2. Find corresponding Dark_facet on boundary of the dark zone + Dark_full_cells dark_incident_s; + for( int i = 0; i <= current_dimension(); ++i ) + { + if( index_of_covertex(light_ft) == i ) + continue; + Dark_v_handle dark_v = light_to_dark[full_cell(light_ft)->vertex(i)]; + dark_incident_s.clear(); + dark_out = std::back_inserter(dark_incident_s); + dark_side.tds().incident_full_cells(dark_v, dark_out); + for(typename Dark_full_cells::iterator it = dark_incident_s.begin(); + it != dark_incident_s.end(); + ++it) + { + (*it)->data().count_ += 1; + } + } + + for( typename Dark_full_cells::iterator it = dark_incident_s.begin(); it != dark_incident_s.end(); ++it ) + { + if( current_dimension() != (*it)->data().count_ ) + continue; + if( ! conflict_zone.contains(*it) ) + continue; + // We found a full_cell incident to the dark facet corresponding to the light facet |light_ft| + int ft_idx = 0; + while( light_s->has_vertex( (*it)->vertex(ft_idx)->data() ) ) + ++ft_idx; + dark_ft = Dark_facet(*it, ft_idx); + break; + } + // Pre-3. Now, we are ready to traverse both boundary and do the stiching. + + // But first, we create the new full_cells in the light triangulation, + // with as much adjacency information as possible. + + // Create new full_cells with vertices + for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it ) + { + Full_cell_handle new_s = new_full_cell(); + (*it)->data().light_copy_ = new_s; + for( int i = 0; i <= current_dimension(); ++i ) + tds().associate_vertex_with_full_cell(new_s, i, (*it)->vertex(i)->data()); + if( dark_ret_s == *it ) + ret_s = new_s; + } + + // Setup adjacencies inside the hole + for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it ) + { + Full_cell_handle new_s = (*it)->data().light_copy_; + for( int i = 0; i <= current_dimension(); ++i ) + if( conflict_zone.contains((*it)->neighbor(i)) ) + tds().set_neighbors(new_s, i, (*it)->neighbor(i)->data().light_copy_, (*it)->mirror_index(i)); + } + + // 3. Stitch + simps.make_searchable(); + typedef std::queue > Queue; + Queue q; + q.push(std::make_pair(light_ft, dark_ft)); + dark_s = dark_side.full_cell(dark_ft); + int dark_i = dark_side.index_of_covertex(dark_ft); + // mark dark_ft as visited: + // TODO try by marking with Dark_v_handle (vertex) + dark_s->neighbor(dark_i)->set_neighbor(dark_s->mirror_index(dark_i), Dark_s_handle()); + while( ! q.empty() ) + { + std::pair p = q.front(); + q.pop(); + light_ft = p.first; + dark_ft = p.second; + light_s = full_cell(light_ft); + int light_i = index_of_covertex(light_ft); + dark_s = dark_side.full_cell(dark_ft); + int dark_i = dark_side.index_of_covertex(dark_ft); + Full_cell_handle light_n = light_s->neighbor(light_i); + set_neighbors(dark_s->data().light_copy_, dark_i, light_n, light_s->mirror_index(light_i)); + for( int di = 0; di <= current_dimension(); ++di ) + { + if( di == dark_i ) + continue; + int li = light_s->index(dark_s->vertex(di)->data()); + Rotor light_r(light_s, li, light_i); + typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); + + while( simps.contains(full_cell(light_r)->neighbor(index_of_covertex(light_r))) ) + light_r = rotate_rotor(light_r); + + while( conflict_zone.contains(dark_side.full_cell(dark_r)->neighbor(dark_side.index_of_covertex(dark_r))) ) + dark_r = dark_side.rotate_rotor(dark_r); + + Dark_s_handle dark_ns = dark_side.full_cell(dark_r); + int dark_ni = dark_side.index_of_covertex(dark_r); + Full_cell_handle light_ns = full_cell(light_r); + int light_ni = index_of_covertex(light_r); + // mark dark_r as visited: + // TODO try by marking with Dark_v_handle (vertex) + Dark_s_handle outside = dark_ns->neighbor(dark_ni); + Dark_v_handle mirror = dark_ns->mirror_vertex(dark_ni, current_dimension()); + int dn = outside->index(mirror); + if( Dark_s_handle() == outside->neighbor(dn) ) + continue; + outside->set_neighbor(dn, Dark_s_handle()); + q.push(std::make_pair(Facet(light_ns, light_ni), Dark_facet(dark_ns, dark_ni))); + } + } + tds().delete_full_cells(simps.begin(), simps.end()); + tds().delete_vertex(v); + return ret_s; +} + +template< typename RTTraits, typename TDS > +void +Regular_triangulation +::remove_decrease_dimension(Vertex_handle v) +{ + CGAL_precondition( current_dimension() >= 0 ); + tds().remove_decrease_dimension(v, infinite_vertex()); + // reset the predicates: + reset_flat_orientation(); + if( 1 <= current_dimension() ) + { + // FIXME: infinite vertex is NOT at index 0 a priori. + Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Orientation o = orientation(s); + CGAL_assertion( ZERO != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS + +template< typename RTTraits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation +::insert(const Weighted_point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) +{ + switch( lt ) + { + case Base::OUTSIDE_AFFINE_HULL: + return insert_outside_affine_hull(p); + break; + case Base::ON_VERTEX: + { + Vertex_handle v = s->vertex(f.index(0)); + v->set_point(p); + return v; + break; + } + default: + if( 1 == current_dimension() ) + { + if( Base::OUTSIDE_CONVEX_HULL == lt ) + { + return insert_outside_convex_hull_1(p, s); + } + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + return v; + } + else + return insert_in_conflicting_cell(p, s); + break; + } +} + +template< typename RTTraits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation +::insert_outside_affine_hull(const Weighted_point & p) +{ + // we don't use Base::insert_outside_affine_hull(...) because here, we + // also need to reset the side_of_oriented_subsphere functor. + CGAL_precondition( current_dimension() < maximal_dimension() ); + Vertex_handle v = tds().insert_increase_dimension(infinite_vertex()); + // reset the predicates: + reset_flat_orientation(); + v->set_point(p); + if( current_dimension() >= 1 ) + { + // FIXME: infinite vertex is NOT at index 0 a priori. + Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Orientation o = orientation(s); + CGAL_assertion( ZERO != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + } + return v; +} + +template< typename RTTraits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation +::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s) +{ + typedef std::vector Full_cell_h_vector; + typedef typename Full_cell_h_vector::iterator SHV_iterator; + static Full_cell_h_vector cs; // for storing conflicting full_cells. + cs.clear(); + // cs.reserve(64); + std::back_insert_iterator out(cs); + Facet ft = compute_conflict_zone(p, s, out); + return insert_in_hole(p, cs.begin(), cs.end(), ft); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES + +// NOT DOCUMENTED +template< typename RTTraits, typename TDS > +template< typename OrientationPred > +Oriented_side +Regular_triangulation +::perturbed_power_test(const Weighted_point & p, Full_cell_const_handle s, + const OrientationPred & ori) const +{ + CGAL_precondition_msg( ! is_infinite(s), "full cell must be finite"); + CGAL_expensive_precondition( POSITIVE == orientation(s) ); + typedef std::vector Points; + Points points(current_dimension() + 2); + int i(0); + for( ; i <= current_dimension(); ++i ) + points[i] = &(s->vertex(i)->point()); + points[i] = &p; + std::sort(points.begin(), points.end(), + internal::Triangulation::Compare_points_for_perturbation(*this)); + typename Points::const_reverse_iterator cut_pt = points.rbegin(); + Points test_points; + while( cut_pt != points.rend() ) + { + if( &p == *cut_pt ) + // because the full_cell "s" is assumed to be positively oriented + return ON_NEGATIVE_SIDE; // we consider |p| to lie outside the sphere + test_points.clear(); + typename Base::Point_const_iterator spit = points_begin(s); + int adjust_sign = -1; + for( i = 0; i < current_dimension(); ++i ) + { + if( &(*spit) == *cut_pt ) + { + ++spit; + adjust_sign = (((current_dimension() + i) % 2) == 0) ? -1 : +1; + } + test_points.push_back(&(*spit)); + ++spit; + } + test_points.push_back(&p); + + typedef typename CGAL::Iterator_project< + typename Points::iterator, + internal::Triangulation::Point_from_pointer, + const Weighted_point &, const Weighted_point * + > Point_pointer_iterator; + + Orientation ori_value = ori( + Point_pointer_iterator(test_points.begin()), + Point_pointer_iterator(test_points.end())); + + if( ZERO != ori_value ) + return Oriented_side( - adjust_sign * ori_value ); + + ++cut_pt; + } + CGAL_assertion(false); // we should never reach here + return ON_NEGATIVE_SIDE; +} + +template< typename RTTraits, typename TDS > +bool +Regular_triangulation +::is_in_conflict(const Weighted_point & p, Full_cell_const_handle s) const +{ + CGAL_precondition( 2 <= current_dimension() ); + if( current_dimension() < maximal_dimension() ) + { + Conflict_pred_in_subspace c( + *this, p, + coaffine_orientation_predicate(), + power_test_in_flat_predicate()); + return c(s); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Power_test_d side = geom_traits().power_test_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + return c(s); + } +} + +template< typename RTTraits, typename TDS > +template< typename OutputIterator > +typename Regular_triangulation::Facet +Regular_triangulation +::compute_conflict_zone(const Weighted_point & p, const Full_cell_handle s, OutputIterator out) const +{ + CGAL_precondition( 2 <= current_dimension() ); + if( current_dimension() < maximal_dimension() ) + { + Conflict_pred_in_subspace c( + *this, p, + coaffine_orientation_predicate(), + power_test_in_flat_predicate()); + Conflict_traversal_pred_in_subspace tp(*this, c); + return tds().gather_full_cells(s, tp, out); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Power_test_d side = geom_traits().power_test_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + Conflict_traversal_pred_in_fullspace tp(*this, c); + return tds().gather_full_cells(s, tp, out); + } +} } //namespace CGAL diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h new file mode 100644 index 00000000000..074ca61e086 --- /dev/null +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -0,0 +1,206 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Clement Jamin + +#ifndef CGAL_REGULAR_TRIANGULATION_EUCLIDEAN_TRAITS_H +#define CGAL_REGULAR_TRIANGULATION_EUCLIDEAN_TRAITS_H + +#include +#include +#include +#include +#include + +#include + +namespace CGAL { + +template < class K, class Weight = typename K::RT > +class Regular_triangulation_euclidean_traits + : public K +{ +public: + typedef K Base; + typedef Regular_triangulation_euclidean_traits Self; + + // Types from K + + typedef K Kernel; + typedef typename K::Dimension Dimension; + typedef typename K::FT FT; + typedef typename K::Point_d Bare_point; + typedef typename K::Weighted_point_d Weighted_point; + typedef Weighted_point Weighted_point_d; + typedef Weighted_point Point_d; + + typedef typename K::Construct_weighted_point_d Construct_weighted_point_d; + typedef typename K::Power_test_d Power_test_d; + typedef typename K::In_flat_power_test_d In_flat_power_test_d; + typedef typename K::Flat_orientation_d Flat_orientation_d; + + //============================================================================= + // Custom types + //============================================================================= + + class Orientation_d + { + const K &m_kernel; + + public: + typedef Orientation result_type; + + Orientation_d(const K &kernel) + : m_kernel(kernel) {} + + template + result_type operator()(ForwardIterator start, ForwardIterator end) const + { + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + return m_kernel.orientation_d_object() ( + boost::make_transform_iterator(start, pdw), + boost::make_transform_iterator(end, pdw) + ); + } + }; + + //============================================================================= + + class Construct_flat_orientation_d + { + const K &m_kernel; + + public: + typedef typename Flat_orientation_d result_type; + + Construct_flat_orientation_d(const K &kernel) + : m_kernel(kernel) {} + + template + result_type operator()(ForwardIterator start, ForwardIterator end) const + { + std::cerr << "start->point()[0]=" << start->point()[0] << std::endl; // CJTODO DEBUG + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + return m_kernel.construct_flat_orientation_d_object() ( + boost::make_transform_iterator(start, pdw), + boost::make_transform_iterator(end, pdw) + ); + } + }; + + + //============================================================================= + + class In_flat_orientation_d + { + const K &m_kernel; + + public: + typedef Orientation result_type; + + In_flat_orientation_d(const K &kernel) + : m_kernel(kernel) {} + + template + result_type operator()(Flat_orientation_d orient, + ForwardIterator start, ForwardIterator end) const + { + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + return m_kernel.in_flat_orientation_d_object() ( + orient, + boost::make_transform_iterator(start, pdw), + boost::make_transform_iterator(end, pdw) + ); + } + }; + + //============================================================================= + + class Contained_in_affine_hull_d + { + const K &m_kernel; + + public: + typedef bool result_type; + + Contained_in_affine_hull_d(const K &kernel) + : m_kernel(kernel) {} + + template + result_type operator()(ForwardIterator start, ForwardIterator end, + const Weighted_point_d & p) const + { + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + return m_kernel.contained_in_affine_hull_d_object() ( + boost::make_transform_iterator(start, pdw), + boost::make_transform_iterator(end, pdw), + pdw(p) + ); + } + }; + + //============================================================================= + + class Compare_lexicographically_d + { + const K &m_kernel; + + public: + typedef Comparison_result result_type; + + Compare_lexicographically_d(const K &kernel) + : m_kernel(kernel) {} + + result_type operator()( + const Weighted_point_d & p, const Weighted_point_d & q) const + { + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + return m_kernel.compare_lexicographically_d_object()(pdw(p), pdw(q)); + } + }; + + + //============================================================================= + // Object creation + //============================================================================= + + Contained_in_affine_hull_d contained_in_affine_hull_d_object() const + { + return Contained_in_affine_hull_d(*this); + } + Orientation_d orientation_d_object() const + { + return Orientation_d(*this); + } + Construct_flat_orientation_d construct_flat_orientation_d_object() const + { + return Construct_flat_orientation_d(*this); + } + In_flat_orientation_d in_flat_orientation_d_object() const + { + return In_flat_orientation_d(*this); + } + Compare_lexicographically_d compare_lexicographically_d_object() const + { + return Compare_lexicographically_d(*this); + } +}; + + +} //namespace CGAL + +#endif // CGAL_REGULAR_TRIANGULATION_EUCLIDEAN_TRAITS_H diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index f1c6d93c4df..30217c40dc0 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -224,6 +224,32 @@ public: { return tds().index_of_covertex(f); } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UTILITIES + + // A co-dimension 2 sub-simplex. called a Rotor because we can rotate + // the two "covertices" around the sub-simplex. Useful for traversing the + // boundary of a hole. NOT DOCUMENTED + typedef cpp11::tuple Rotor; + Full_cell_handle full_cell(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<0>(r); + } + int index_of_covertex(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<1>(r); + } + int index_of_second_covertex(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<2>(r); + } + Rotor rotate_rotor(Rotor & r) // NOT DOCUMENTED... + { + int opposite = full_cell(r)->mirror_index(index_of_covertex(r)); + Full_cell_handle s = full_cell(r)->neighbor(index_of_covertex(r)); + int new_second = s->index(full_cell(r)->vertex(index_of_second_covertex(r))); + return Rotor(s, new_second, opposite); + } // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS @@ -568,7 +594,7 @@ public: } else { - return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); + return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); } } @@ -702,6 +728,28 @@ public: // make sure all full_cells have positive orientation void reorient_full_cells(); +protected: + // This is used in the |remove(v)| member function to manage sets of Full_cell_handles + template< typename FCH > + struct Full_cell_set : public std::vector + { + typedef std::vector Base_set; + using Base_set::begin; + using Base_set::end; + void make_searchable() + { // sort the full cell handles + std::sort(begin(), end()); + } + bool contains(const FCH & fch) const + { + return std::binary_search(begin(), end(), fch); + } + bool contains_1st_and_not_2nd(const FCH & fst, const FCH & snd) const + { + return ( ! contains(snd) ) && ( contains(fst) ); + } + }; + }; // Triangulation<...> // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = diff --git a/Triangulation/include/CGAL/internal/Triangulation/utilities.h b/Triangulation/include/CGAL/internal/Triangulation/utilities.h index ab44bb80ff2..8392a064324 100644 --- a/Triangulation/include/CGAL/internal/Triangulation/utilities.h +++ b/Triangulation/include/CGAL/internal/Triangulation/utilities.h @@ -96,7 +96,7 @@ public: template< class T > struct Compare_points_for_perturbation { - typedef typename T::Point_d Point; + typedef typename T::Geom_traits::Point_d Point; const T & t_; @@ -117,8 +117,8 @@ public: template< class T > struct Point_from_pointer { - typedef const typename T::Point_d * argument_type; - typedef const typename T::Point_d result_type; + typedef const typename T::Geom_traits::Point_d * argument_type; + typedef const typename T::Geom_traits::Point_d result_type; result_type & operator()(argument_type & x) const { return (*x); diff --git a/Triangulation/test/Triangulation/regular.cpp b/Triangulation/test/Triangulation/regular.cpp new file mode 100644 index 00000000000..67d8eefadef --- /dev/null +++ b/Triangulation/test/Triangulation/regular.cpp @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; + +template +void test(const int d, const string & type, const int N) +{ + typedef typename RTri::Vertex Vertex; + typedef typename RTri::Vertex_handle Vertex_handle; + typedef typename RTri::Full_cell Full_cell; + typedef typename RTri::Full_cell_handle Full_cell_handle; + typedef typename RTri::Facet Facet; + typedef typename RTri::Face Face; + typedef typename RTri::Point Point; + typedef typename RTri::Bare_point Bare_point; + typedef typename RTri::Finite_full_cell_const_iterator Finite_full_cell_const_iterator; + typedef typename RTri::Finite_vertex_iterator Finite_vertex_iterator; + + typedef CGAL::Random_points_in_cube_d Random_points_iterator; + + RTri pc(d); + cerr << "\nBuilding Regular triangulation of (" << type << d << ") dimension with " << N << " points"; + assert(pc.empty()); + + vector points; + CGAL::Random rng; + Random_points_iterator rand_it(d, 2.0, rng); // CJTODO: unused + + for( int i = 0; i < N; ++i ) + { + vector coords(d); + for( int j = 0; j < d; ++j ) + coords[j] = static_cast(rand() % 100000)/10000; + points.push_back( + Point(Bare_point(d, coords.begin(), coords.end()), + rand() % 10)); + } + pc.insert(points.begin(), points.end()); + cerr << "\nChecking topology and geometry..."; + assert( pc.is_valid() ); + + cerr << "\nTraversing finite full_cells... "; + size_t nbfs(0), nbis(0); + Finite_full_cell_const_iterator fsit = pc.finite_full_cells_begin(); + while( fsit != pc.finite_full_cells_end() ) + ++fsit, ++nbfs; + cerr << nbfs << " + "; + vector infinite_full_cells; + pc.tds().incident_full_cells(pc.infinite_vertex(), back_inserter(infinite_full_cells)); + nbis = infinite_full_cells.size(); + cerr << nbis << " = " << (nbis+nbfs) + << " = " << pc.number_of_full_cells(); + cerr << "\nThe triangulation has current dimension " << pc.current_dimension(); + CGAL_assertion( pc.number_of_full_cells() == nbis+nbfs); + + cerr << "\nTraversing finite vertices... "; + size_t nbfv(0); + Finite_vertex_iterator fvit = pc.finite_vertices_begin(); + while( fvit != pc.finite_vertices_end() ) + ++fvit, ++nbfv; + cerr << nbfv < 1 ) + { + typedef vector Faces; + Faces edges; + back_insert_iterator out(edges); + pc.tds().incident_faces(pc.infinite_vertex(), 1, out); + cout << "\nThere are " << edges.size() << " vertices on the convex hull."; + edges.clear(); + } + else // pc.maximal_dimension() == 1 + { + typedef vector Cells; + Cells cells; + back_insert_iterator out(cells); + pc.tds().incident_full_cells(pc.infinite_vertex(), out); + cout << "\nThere are " << cells.size() << " vertices on the convex hull."; + cells.clear(); + } + + // Remove all ! + cerr << "\nBefore removal: " << pc.number_of_vertices() << " vertices. After: "; + random_shuffle(points.begin(), points.end()); + pc.remove(points.begin(), points.end()); + assert( pc.is_valid() ); + cerr << pc.number_of_vertices() << " vertices."; + // assert( pc.empty() ); NOT YET ! + // CLEAR + pc.clear(); + assert( -1 == pc.current_dimension() ); + assert( pc.empty() ); + assert( pc.is_valid() ); +} + +template< int D > +void go(const int N) +{ + //typedef CGAL::Epick_d FK; + typedef CGAL::Epick_d > FK; + typedef CGAL::Regular_triangulation_euclidean_traits Traits; + typedef CGAL::Regular_triangulation Triangulation; + //test(D, "dynamic", N); + test(D, "static", N); +} + +int main(int argc, char **argv) +{ + srand(static_cast(time(NULL))); + int N = 10; + if( argc > 1 ) + N = atoi(argv[1]); + //go<5>(N); + //go<4>(N); + //go<3>(N); + go<2>(N); + //go<1>(N); + + cerr << endl; + return 0; +} From 25a319f4a5b58962006e1567ec0690e3d2eeb552 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 13 Jun 2014 15:33:22 +0200 Subject: [PATCH 011/487] Fix compilation with GCC --- .../CGAL/NewKernel_d/KernelD_converter.h | 10 +++++----- .../include/CGAL/Delaunay_triangulation.h | 7 ++++--- .../include/CGAL/Regular_triangulation.h | 20 +++++++++---------- .../Regular_triangulation_euclidean_traits.h | 3 ++- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h b/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h index bb56e8648da..c4ef7304d64 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h @@ -93,7 +93,7 @@ class KernelD_converter_ //typedef typename KOC::argument_type K1_Obj; //typedef typename KOC::result_type K2_Obj; public: - void disp(const std::array &o) const // CJTODO DEBUG + /*void disp(const std::array &o) const // CJTODO DEBUG { std::cerr << o[0]; } @@ -101,7 +101,7 @@ class KernelD_converter_ void disp(const P &o) const // CJTODO DEBUG { std::cerr << o.point()[0] ; - } + }*/ using Base::operator(); // don't use directly, just make it accessible to the next level K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD true_type)const{ return KOC()(this->myself().kernel(),this->myself().kernel2(),this->myself(),o); @@ -110,9 +110,9 @@ class KernelD_converter_ return K1_Conv(this->myself().kernel())(this->myself().kernel2(),this->myself(),o); } K2_Obj operator()(argument_type const& o)const{ - std::cerr << "KernelD_converter_::operator() "; // CJTODO DEBUG - disp(o); - std::cerr << std::endl; + //std::cerr << "KernelD_converter_::operator() "; // CJTODO DEBUG + //disp(o); + //std::cerr << std::endl; return helper(o,no_converter()); } template struct result:Base::template result{}; diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 78dd0e06d01..ba8702c8ae7 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -86,7 +86,8 @@ protected: // DATA MEMBERS public: - + + using typename Base::Rotor; using Base::maximal_dimension; using Base::are_incident_full_cells_valid; using Base::coaffine_orientation_predicate; @@ -383,7 +384,7 @@ Delaunay_triangulation // THE CASE cur_dim >= 2 // Gather the finite vertices sharing an edge with |v| - typedef Base::Full_cell_set Simplices; + typedef typename Base::template Full_cell_set Simplices; Simplices simps; std::back_insert_iterator out(simps); tds().incident_full_cells(v, out); @@ -519,7 +520,7 @@ Delaunay_triangulation Dark_s_handle dark_ret_s = dark_s; Full_cell_handle ret_s; - typedef Base::Full_cell_set Dark_full_cells; + typedef typename Base::template Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 3e271b13998..f40f1c55bc5 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -91,7 +91,8 @@ protected: // DATA MEMBERS public: - + + using typename Base::Rotor; using Base::maximal_dimension; using Base::are_incident_full_cells_valid; using Base::coaffine_orientation_predicate; @@ -99,6 +100,8 @@ public: using Base::current_dimension; using Base::geom_traits; using Base::index_of_covertex; + using Base::index_of_second_covertex; + using Base::rotate_rotor; using Base::infinite_vertex; using Base::insert_in_hole; using Base::insert_outside_convex_hull_1; @@ -120,9 +123,6 @@ public: private: //*** Power_test_in_flat_d *** CJTODO: better name? - typedef typename Base::Flat_orientation_d Flat_orientation_d; - typedef typename Base::Construct_flat_orientation_d Construct_flat_orientation_d; - typedef typename RTTraits::In_flat_power_test_d In_flat_power_test_d; // Wrapper struct Power_test_in_flat_d { @@ -215,16 +215,16 @@ public: size_type n = number_of_vertices(); typedef std::vector WP_vec; WP_vec points(start, end); - Geom_traits::Point_drop_weight_d pdw = + typename Geom_traits::Point_drop_weight_d pdw = geom_traits().point_drop_weight_d_object(); spatial_sort( boost::make_transform_iterator(points.begin(), pdw), boost::make_transform_iterator(points.end(), pdw), - Geom_traits::Base()); + typename Geom_traits::Base()); //spatial_sort(points.begin(), points.end(), geom_traits()); // CJTODO TEMP A REMETTRE //spatial_sort(points.begin(), points.end(), Geom_traits::Base()); Full_cell_handle hint; - for(WP_vec::const_iterator p = points.begin(); p != points.end(); ++p ) + for(typename WP_vec::const_iterator p = points.begin(); p != points.end(); ++p ) { Locate_type lt; Face f(maximal_dimension()); @@ -408,7 +408,7 @@ Regular_triangulation // THE CASE cur_dim >= 2 // Gather the finite vertices sharing an edge with |v| - typedef Base::Full_cell_set Simplices; + typedef typename Base::template Full_cell_set Simplices; Simplices simps; std::back_insert_iterator out(simps); tds().incident_full_cells(v, out); @@ -548,7 +548,7 @@ Regular_triangulation Dark_s_handle dark_ret_s = dark_s; Full_cell_handle ret_s; - typedef Base::Full_cell_set Dark_full_cells; + typedef typename Base::template Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); @@ -885,4 +885,4 @@ Regular_triangulation } //namespace CGAL -#endif CGAL_REGULAR_TRIANGULATION_H +#endif //CGAL_REGULAR_TRIANGULATION_H diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 074ca61e086..7a3f5e64487 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -52,6 +52,7 @@ public: typedef typename K::Power_test_d Power_test_d; typedef typename K::In_flat_power_test_d In_flat_power_test_d; typedef typename K::Flat_orientation_d Flat_orientation_d; + typedef typename K::Point_drop_weight_d Point_drop_weight_d; //============================================================================= // Custom types @@ -85,7 +86,7 @@ public: const K &m_kernel; public: - typedef typename Flat_orientation_d result_type; + typedef Flat_orientation_d result_type; Construct_flat_orientation_d(const K &kernel) : m_kernel(kernel) {} From a94ed180927d7bbae61d5286ed9e5da46fc88fbf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 13 Jun 2014 16:09:51 +0200 Subject: [PATCH 012/487] Just test dim 2 for now --- Triangulation/test/Triangulation/triangulation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation/test/Triangulation/triangulation.cpp b/Triangulation/test/Triangulation/triangulation.cpp index 96f427efea1..8f6bd1f6453 100644 --- a/Triangulation/test/Triangulation/triangulation.cpp +++ b/Triangulation/test/Triangulation/triangulation.cpp @@ -119,10 +119,10 @@ int main(int argc, char **argv) int N = 1000; if( argc > 1 ) N = atoi(argv[1]); - go<5>(N); - go<3>(N); + //go<5>(N); + //go<3>(N); go<2>(N); - go<1>(N); + //go<1>(N); cerr << std::endl; return 0; From 92de88555f85ba49e5784b0d66d66dfcef44495c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 13 Jun 2014 19:12:34 +0200 Subject: [PATCH 013/487] More debug traces --- NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h | 5 +++++ Triangulation/include/CGAL/Regular_triangulation.h | 1 + .../include/CGAL/Regular_triangulation_euclidean_traits.h | 5 ++++- Triangulation/include/CGAL/Triangulation.h | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h index c8f1950ce13..293e91453bd 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h @@ -78,6 +78,10 @@ template struct Construct_flat_orientation : private Store_kernel // the points are affinely independent. template result_type operator()(Iter f, Iter e)const{ + std::cerr << "Kernel flat orientation - points: " ; // CJTODO DEBUG + for (Iter it = f ; it != e ; ++it) + std::cerr << (*it)[0] << " "; + std::cerr << std::endl; // CJTODO DEBUG Iter f_save = f; PD pd (this->kernel()); CCC ccc (this->kernel()); @@ -89,6 +93,7 @@ template struct Construct_flat_orientation : private Store_kernel std::vector& rest=o.rest; rest.reserve(dim+1); for(int i=0; ipoint()[0] << " " << p->point()[1] << std::endl; Full_cell_handle c = locate (*p, lt, f, ft, hint); Vertex_handle v = insert (*p, lt, f, ft, c); diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 7a3f5e64487..a73230db573 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -94,7 +94,10 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - std::cerr << "start->point()[0]=" << start->point()[0] << std::endl; // CJTODO DEBUG + std::cerr << "Traits flat orientation - points: " ; // CJTODO DEBUG + for (ForwardIterator it = start ; it != end ; ++it) + std::cerr << (*it).point()[0] << " "; + std::cerr << std::endl; // CJTODO DEBUG Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.construct_flat_orientation_d_object() ( boost::make_transform_iterator(start, pdw), diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 30217c40dc0..5261daf36b9 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -594,6 +594,10 @@ public: } else { + std::cerr << "orientation points: " ; // CJTODO DEBUG + for (auto it = points_begin(s) ; it != points_begin(s) + 1 + current_dimension() ; ++it) + std::cerr << (*it).point()[0] << " "; + std::cerr << std::endl; // CJTODO DEBUG return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); } } From 286d476f68ec2283bf2b13ea1c1ec4df1b5c054f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sat, 14 Jun 2014 08:14:59 +0200 Subject: [PATCH 014/487] Use lower weights --- Triangulation/test/Triangulation/regular.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Triangulation/test/Triangulation/regular.cpp b/Triangulation/test/Triangulation/regular.cpp index 67d8eefadef..0d481321614 100644 --- a/Triangulation/test/Triangulation/regular.cpp +++ b/Triangulation/test/Triangulation/regular.cpp @@ -41,14 +41,15 @@ void test(const int d, const string & type, const int N) { vector coords(d); for( int j = 0; j < d; ++j ) - coords[j] = static_cast(rand() % 100000)/10000; - points.push_back( - Point(Bare_point(d, coords.begin(), coords.end()), - rand() % 10)); + coords[j] = static_cast(rand() % 100000)/10000; + points.push_back(Point( + Bare_point(d, coords.begin(), coords.end()), + static_cast(rand() % 100000)/100000 + )); } pc.insert(points.begin(), points.end()); cerr << "\nChecking topology and geometry..."; - assert( pc.is_valid() ); + assert( pc.is_valid(true) ); cerr << "\nTraversing finite full_cells... "; size_t nbfs(0), nbis(0); From 9277e907db707b693da322093680ffd9c94f07da Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sat, 14 Jun 2014 08:16:30 +0200 Subject: [PATCH 015/487] Commented the traces out --- .../include/CGAL/NewKernel_d/Coaffine.h | 4 ++-- .../CGAL/NewKernel_d/KernelD_converter.h | 23 +++++++++++++------ Triangulation/include/CGAL/Triangulation.h | 4 ++-- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h index 293e91453bd..3a27eee90ff 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h @@ -78,10 +78,10 @@ template struct Construct_flat_orientation : private Store_kernel // the points are affinely independent. template result_type operator()(Iter f, Iter e)const{ - std::cerr << "Kernel flat orientation - points: " ; // CJTODO DEBUG + /*std::cerr << "Kernel flat orientation - points: " ; // CJTODO DEBUG for (Iter it = f ; it != e ; ++it) std::cerr << (*it)[0] << " "; - std::cerr << std::endl; // CJTODO DEBUG + std::cerr << std::endl; // CJTODO DEBUG*/ Iter f_save = f; PD pd (this->kernel()); CCC ccc (this->kernel()); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h b/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h index c4ef7304d64..382e2cb92f5 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h @@ -93,15 +93,22 @@ class KernelD_converter_ //typedef typename KOC::argument_type K1_Obj; //typedef typename KOC::result_type K2_Obj; public: - /*void disp(const std::array &o) const // CJTODO DEBUG +#if defined(BOOST_MSVC) + void disp(const std::array &o) const // CJTODO DEBUG { - std::cerr << o[0]; + std::cerr << o[0] << " (std::array)"; } +#else + void disp(const cpp11::array &o) const // CJTODO DEBUG + { + std::cerr << o[0] << " (cpp11::array)"; + } +#endif template void disp(const P &o) const // CJTODO DEBUG { - std::cerr << o.point()[0] ; - }*/ + std::cerr << o.point()[0] << " (Point)"; + } using Base::operator(); // don't use directly, just make it accessible to the next level K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD true_type)const{ return KOC()(this->myself().kernel(),this->myself().kernel2(),this->myself(),o); @@ -110,9 +117,11 @@ class KernelD_converter_ return K1_Conv(this->myself().kernel())(this->myself().kernel2(),this->myself(),o); } K2_Obj operator()(argument_type const& o)const{ - //std::cerr << "KernelD_converter_::operator() "; // CJTODO DEBUG - //disp(o); - //std::cerr << std::endl; + /*std::cerr << "KernelD_converter_::operator() "; // CJTODO DEBUG + disp(o); + std::cerr << std::endl;*/ + //K2_Obj k2o = helper(o,no_converter()); + //disp(k2o); return helper(o,no_converter()); } template struct result:Base::template result{}; diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 5261daf36b9..8d90a185bbf 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -594,10 +594,10 @@ public: } else { - std::cerr << "orientation points: " ; // CJTODO DEBUG + /*std::cerr << "orientation points: " ; // CJTODO DEBUG for (auto it = points_begin(s) ; it != points_begin(s) + 1 + current_dimension() ; ++it) std::cerr << (*it).point()[0] << " "; - std::cerr << std::endl; // CJTODO DEBUG + std::cerr << std::endl; // CJTODO DEBUG*/ return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); } } From d829e61fd1bbc5f2fde5d66d59802264580ccbef Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sat, 14 Jun 2014 08:17:16 +0200 Subject: [PATCH 016/487] Temporary ugly code that runs without crashing --- .../Regular_triangulation_euclidean_traits.h | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index a73230db573..69d6f5a9d27 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -72,9 +72,14 @@ public: result_type operator()(ForwardIterator start, ForwardIterator end) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + std::vector points; + while (start != end) + { + points.push_back(pdw(*start)); + ++start; + } return m_kernel.orientation_d_object() ( - boost::make_transform_iterator(start, pdw), - boost::make_transform_iterator(end, pdw) + points.begin(), points.end() ); } }; @@ -94,15 +99,19 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - std::cerr << "Traits flat orientation - points: " ; // CJTODO DEBUG + /*std::cerr << "Traits flat orientation - points: " ; // CJTODO DEBUG for (ForwardIterator it = start ; it != end ; ++it) std::cerr << (*it).point()[0] << " "; - std::cerr << std::endl; // CJTODO DEBUG + std::cerr << std::endl; // CJTODO DEBUG*/ Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + std::vector points; + while (start != end) + { + points.push_back(pdw(*start)); + ++start; + } return m_kernel.construct_flat_orientation_d_object() ( - boost::make_transform_iterator(start, pdw), - boost::make_transform_iterator(end, pdw) - ); + points.begin(), points.end()); } }; @@ -124,10 +133,15 @@ public: ForwardIterator start, ForwardIterator end) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + std::vector points; + while (start != end) + { + points.push_back(pdw(*start)); + ++start; + } return m_kernel.in_flat_orientation_d_object() ( orient, - boost::make_transform_iterator(start, pdw), - boost::make_transform_iterator(end, pdw) + points.begin(), points.end() ); } }; @@ -149,9 +163,14 @@ public: const Weighted_point_d & p) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + std::vector points; + while (start != end) + { + points.push_back(pdw(*start)); + ++start; + } return m_kernel.contained_in_affine_hull_d_object() ( - boost::make_transform_iterator(start, pdw), - boost::make_transform_iterator(end, pdw), + points.begin(), points.end(), pdw(p) ); } From 750f09c3c4c0a86bdabd16f897d980aa40a83d58 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 14 Jun 2014 23:50:14 +0200 Subject: [PATCH 017/487] Temporarily make Forward_rep copy, I am not sure how best to avoid returning references to temporaries without copying (or moving). --- .../include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h index 520a96c8e9e..43ed894e4e5 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h @@ -79,16 +79,17 @@ struct Forward_rep { //}; //#else template ::value,bool=Is_wrapper_iterator::value> struct result_; -template struct result_{typedef T const& type;}; -template struct result_{typedef typename decay::type::Rep const& type;}; +template struct result_{typedef T type;}; // const& +template struct result_{typedef typename decay::type::Rep type;}; // const& template struct result_{typedef transforming_iterator::type> type;}; template struct result; template struct result : result_ {}; -template typename boost::disable_if,Is_wrapper_iterator >,T>::type const& operator()(T const& t) const {return t;} +template typename boost::disable_if,Is_wrapper_iterator >,T>::type operator()(T const& t) const {return t;} // const& template typename boost::disable_if,Is_wrapper_iterator >,T>::type& operator()(T& t) const {return t;} -template typename T::Rep const& operator()(T const& t, typename boost::enable_if >::type* = 0) const {return t.rep();} +// FIXME: We should return const&, but it causes trouble inside a transform_iterator of an iterator that returns a prvalue :-( +template typename T::Rep operator()(T const& t, typename boost::enable_if >::type* = 0) const {return t.rep();} template transforming_iterator,T>::type> operator()(T const& t) const {return make_transforming_iterator(t,Forward_rep());} //#endif From 41a312bca37e4c885be0565f704ad1a688c7a89d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 16 Jun 2014 08:06:52 +0200 Subject: [PATCH 018/487] Revert "Temporary ugly code that runs without crashing" Now it works. This reverts commit d829e61fd1bbc5f2fde5d66d59802264580ccbef. --- .../Regular_triangulation_euclidean_traits.h | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 69d6f5a9d27..30ad449d967 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -72,14 +72,9 @@ public: result_type operator()(ForwardIterator start, ForwardIterator end) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - std::vector points; - while (start != end) - { - points.push_back(pdw(*start)); - ++start; - } return m_kernel.orientation_d_object() ( - points.begin(), points.end() + boost::make_transform_iterator(start, pdw), + boost::make_transform_iterator(end, pdw) ); } }; @@ -104,14 +99,10 @@ public: std::cerr << (*it).point()[0] << " "; std::cerr << std::endl; // CJTODO DEBUG*/ Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - std::vector points; - while (start != end) - { - points.push_back(pdw(*start)); - ++start; - } return m_kernel.construct_flat_orientation_d_object() ( - points.begin(), points.end()); + boost::make_transform_iterator(start, pdw), + boost::make_transform_iterator(end, pdw) + ); } }; @@ -133,15 +124,10 @@ public: ForwardIterator start, ForwardIterator end) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - std::vector points; - while (start != end) - { - points.push_back(pdw(*start)); - ++start; - } return m_kernel.in_flat_orientation_d_object() ( orient, - points.begin(), points.end() + boost::make_transform_iterator(start, pdw), + boost::make_transform_iterator(end, pdw) ); } }; @@ -163,14 +149,9 @@ public: const Weighted_point_d & p) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - std::vector points; - while (start != end) - { - points.push_back(pdw(*start)); - ++start; - } return m_kernel.contained_in_affine_hull_d_object() ( - points.begin(), points.end(), + boost::make_transform_iterator(start, pdw), + boost::make_transform_iterator(end, pdw), pdw(p) ); } From d141311a5b6166ca2ffac86e04704feb2238d514 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 16 Jun 2014 09:25:24 +0200 Subject: [PATCH 019/487] Some operator<< for the points --- .../include/CGAL/IO/Triangulation_io.h | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Triangulation/include/CGAL/IO/Triangulation_io.h diff --git a/Triangulation/include/CGAL/IO/Triangulation_io.h b/Triangulation/include/CGAL/IO/Triangulation_io.h new file mode 100644 index 00000000000..89c3bc4bd33 --- /dev/null +++ b/Triangulation/include/CGAL/IO/Triangulation_io.h @@ -0,0 +1,63 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// Author(s) : Clement Jamin + + +#ifndef CGAL_TRIANGULATION_IO_H +#define CGAL_TRIANGULATION_IO_H + +#include +#include +#include +#include + +namespace CGAL { + +template +std::ostream & +operator<<(std::ostream & os, const typename Wrap::Point_d & p) +{ + typename K::Cartesian_const_iterator_d it = p.cartesian_begin(); + os << "(" << *it; + ++it; + for ( ; it != p.cartesian_end() ; ++it) + { + os << ", " << *it; + } + os << ")"; + return os; +} + +template +std::ostream & +operator<<(std::ostream & os, const typename Wrap::Weighted_point_d & p) +{ + return os << p.point(); +} + +/*template< class A, class B > +std::ostream & +operator<<(std::ostream & os, const Triangulation_vertex & v) +{ + os << v.point(); + return os; +}*/ + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_IO_H From 9055e2717574907e982b29b77914ac80d933820d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 16 Jun 2014 09:26:14 +0200 Subject: [PATCH 020/487] Improve output + variable renaming --- .../CGAL/Triangulation_data_structure.h | 2 +- Triangulation/test/Triangulation/delaunay.cpp | 72 ++++++++++--------- Triangulation/test/Triangulation/regular.cpp | 58 ++++++++------- 3 files changed, 70 insertions(+), 62 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index c9d073dca69..9c4f3239a14 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -1533,7 +1533,7 @@ operator<<(std::ostream & os, const Triangulation_data_structure int i = 0; for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it, ++i ) { - os << *it; // write the vertex + os << *it << std::endl; // write the vertex index_of_vertex[it] = i; } CGAL_assertion( i == n ); diff --git a/Triangulation/test/Triangulation/delaunay.cpp b/Triangulation/test/Triangulation/delaunay.cpp index 38ea692aba8..3a0dad37f07 100644 --- a/Triangulation/test/Triangulation/delaunay.cpp +++ b/Triangulation/test/Triangulation/delaunay.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -32,79 +33,82 @@ void test(const int d, const string & type, const int N) typedef CGAL::Random_points_in_cube_d Random_points_iterator; - DC pc(d); + DC dt(d); cerr << "\nBuilding Delaunay triangulation of (" << type << d << ") dimension with " << N << " points"; - assert(pc.empty()); + assert(dt.empty()); vector points; - CGAL::Random rng; - Random_points_iterator rand_it(d, 2.0, rng); + //CGAL::Random rng; + //Random_points_iterator rand_it(d, 2.0, rng); //CGAL::cpp11::copy_n(rand_it, N, back_inserter(points)); - vector coords(d); + srand(10); for( int i = 0; i < N; ++i ) { + vector coords(d); for( int j = 0; j < d; ++j ) - coords[j] = rand() % 100000; + coords[j] = static_cast(rand() % 100000)/10000; points.push_back(Point(d, coords.begin(), coords.end())); } - pc.insert(points.begin(), points.end()); + dt.insert(points.begin(), points.end()); cerr << "\nChecking topology and geometry..."; - assert( pc.is_valid() ); + assert( dt.is_valid() ); cerr << "\nTraversing finite full_cells... "; size_t nbfs(0), nbis(0); - Finite_full_cell_const_iterator fsit = pc.finite_full_cells_begin(); - while( fsit != pc.finite_full_cells_end() ) + Finite_full_cell_const_iterator fsit = dt.finite_full_cells_begin(); + while( fsit != dt.finite_full_cells_end() ) ++fsit, ++nbfs; cerr << nbfs << " + "; vector infinite_full_cells; - pc.tds().incident_full_cells(pc.infinite_vertex(), back_inserter(infinite_full_cells)); + dt.tds().incident_full_cells(dt.infinite_vertex(), back_inserter(infinite_full_cells)); nbis = infinite_full_cells.size(); cerr << nbis << " = " << (nbis+nbfs) - << " = " << pc.number_of_full_cells(); - cerr << "\nThe triangulation has current dimension " << pc.current_dimension(); - CGAL_assertion( pc.number_of_full_cells() == nbis+nbfs); + << " = " << dt.number_of_full_cells(); + cerr << "\nThe triangulation has current dimension " << dt.current_dimension(); + CGAL_assertion( dt.number_of_full_cells() == nbis+nbfs); cerr << "\nTraversing finite vertices... "; size_t nbfv(0); - Finite_vertex_iterator fvit = pc.finite_vertices_begin(); - while( fvit != pc.finite_vertices_end() ) + Finite_vertex_iterator fvit = dt.finite_vertices_begin(); + while( fvit != dt.finite_vertices_end() ) ++fvit, ++nbfv; cerr << nbfv < 1 ) + if( dt.maximal_dimension() > 1 ) { typedef vector Faces; Faces edges; back_insert_iterator out(edges); - pc.tds().incident_faces(pc.infinite_vertex(), 1, out); + dt.tds().incident_faces(dt.infinite_vertex(), 1, out); cout << "\nThere are " << edges.size() << " vertices on the convex hull."; edges.clear(); } - else // pc.maximal_dimension() == 1 + else // dt.maximal_dimension() == 1 { typedef vector Cells; Cells cells; back_insert_iterator out(cells); - pc.tds().incident_full_cells(pc.infinite_vertex(), out); + dt.tds().incident_full_cells(dt.infinite_vertex(), out); cout << "\nThere are " << cells.size() << " vertices on the convex hull."; cells.clear(); } + + cout << dt.tds() << std::endl; // Remove all ! - cerr << "\nBefore removal: " << pc.number_of_vertices() << " vertices. After: "; + cerr << "\nBefore removal: " << dt.number_of_vertices() << " vertices. After: "; random_shuffle(points.begin(), points.end()); - pc.remove(points.begin(), points.end()); - assert( pc.is_valid() ); - cerr << pc.number_of_vertices() << " vertices."; - // assert( pc.empty() ); NOT YET ! + dt.remove(points.begin(), points.end()); + assert( dt.is_valid() ); + cerr << dt.number_of_vertices() << " vertices."; + // assert( dt.empty() ); NOT YET ! // CLEAR - pc.clear(); - assert( -1 == pc.current_dimension() ); - assert( pc.empty() ); - assert( pc.is_valid() ); + dt.clear(); + assert( -1 == dt.current_dimension() ); + assert( dt.empty() ); + assert( dt.is_valid() ); } template< int D > @@ -120,14 +124,14 @@ void go(const int N) int main(int argc, char **argv) { srand(static_cast(time(NULL))); - int N = 100; + int N = 10; if( argc > 1 ) N = atoi(argv[1]); - go<5>(N); - go<4>(N); - go<3>(N); + //go<5>(N); + //go<4>(N); + //go<3>(N); go<2>(N); - go<1>(N); + //go<1>(N); cerr << endl; return 0; diff --git a/Triangulation/test/Triangulation/regular.cpp b/Triangulation/test/Triangulation/regular.cpp index 0d481321614..1956651c682 100644 --- a/Triangulation/test/Triangulation/regular.cpp +++ b/Triangulation/test/Triangulation/regular.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -29,14 +30,15 @@ void test(const int d, const string & type, const int N) typedef CGAL::Random_points_in_cube_d Random_points_iterator; - RTri pc(d); + RTri rt(d); cerr << "\nBuilding Regular triangulation of (" << type << d << ") dimension with " << N << " points"; - assert(pc.empty()); + assert(rt.empty()); vector points; - CGAL::Random rng; - Random_points_iterator rand_it(d, 2.0, rng); // CJTODO: unused + //CGAL::Random rng; + //Random_points_iterator rand_it(d, 2.0, rng); // CJTODO: unused + srand(10); for( int i = 0; i < N; ++i ) { vector coords(d); @@ -47,63 +49,65 @@ void test(const int d, const string & type, const int N) static_cast(rand() % 100000)/100000 )); } - pc.insert(points.begin(), points.end()); + rt.insert(points.begin(), points.end()); cerr << "\nChecking topology and geometry..."; - assert( pc.is_valid(true) ); + assert( rt.is_valid(true) ); cerr << "\nTraversing finite full_cells... "; size_t nbfs(0), nbis(0); - Finite_full_cell_const_iterator fsit = pc.finite_full_cells_begin(); - while( fsit != pc.finite_full_cells_end() ) + Finite_full_cell_const_iterator fsit = rt.finite_full_cells_begin(); + while( fsit != rt.finite_full_cells_end() ) ++fsit, ++nbfs; cerr << nbfs << " + "; vector infinite_full_cells; - pc.tds().incident_full_cells(pc.infinite_vertex(), back_inserter(infinite_full_cells)); + rt.tds().incident_full_cells(rt.infinite_vertex(), back_inserter(infinite_full_cells)); nbis = infinite_full_cells.size(); cerr << nbis << " = " << (nbis+nbfs) - << " = " << pc.number_of_full_cells(); - cerr << "\nThe triangulation has current dimension " << pc.current_dimension(); - CGAL_assertion( pc.number_of_full_cells() == nbis+nbfs); + << " = " << rt.number_of_full_cells(); + cerr << "\nThe triangulation has current dimension " << rt.current_dimension(); + CGAL_assertion( rt.number_of_full_cells() == nbis+nbfs); cerr << "\nTraversing finite vertices... "; size_t nbfv(0); - Finite_vertex_iterator fvit = pc.finite_vertices_begin(); - while( fvit != pc.finite_vertices_end() ) + Finite_vertex_iterator fvit = rt.finite_vertices_begin(); + while( fvit != rt.finite_vertices_end() ) ++fvit, ++nbfv; cerr << nbfv < 1 ) + if( rt.maximal_dimension() > 1 ) { typedef vector Faces; Faces edges; back_insert_iterator out(edges); - pc.tds().incident_faces(pc.infinite_vertex(), 1, out); + rt.tds().incident_faces(rt.infinite_vertex(), 1, out); cout << "\nThere are " << edges.size() << " vertices on the convex hull."; edges.clear(); } - else // pc.maximal_dimension() == 1 + else // rt.maximal_dimension() == 1 { typedef vector Cells; Cells cells; back_insert_iterator out(cells); - pc.tds().incident_full_cells(pc.infinite_vertex(), out); + rt.tds().incident_full_cells(rt.infinite_vertex(), out); cout << "\nThere are " << cells.size() << " vertices on the convex hull."; cells.clear(); } + cout << rt.tds() << std::endl; + // Remove all ! - cerr << "\nBefore removal: " << pc.number_of_vertices() << " vertices. After: "; + cerr << "\nBefore removal: " << rt.number_of_vertices() << " vertices. After: "; random_shuffle(points.begin(), points.end()); - pc.remove(points.begin(), points.end()); - assert( pc.is_valid() ); - cerr << pc.number_of_vertices() << " vertices."; - // assert( pc.empty() ); NOT YET ! + rt.remove(points.begin(), points.end()); + assert( rt.is_valid() ); + cerr << rt.number_of_vertices() << " vertices."; + // assert( rt.empty() ); NOT YET ! // CLEAR - pc.clear(); - assert( -1 == pc.current_dimension() ); - assert( pc.empty() ); - assert( pc.is_valid() ); + rt.clear(); + assert( -1 == rt.current_dimension() ); + assert( rt.empty() ); + assert( rt.is_valid() ); } template< int D > From 907f7bec01b07d75bdc212ab52d98a6703d7c0f4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 16 Jun 2014 11:44:06 +0200 Subject: [PATCH 021/487] Export to OFF (2D & 3D triangulations) --- .../include/CGAL/IO/Triangulation_io.h | 89 ++++++++++++++++++- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/Triangulation/include/CGAL/IO/Triangulation_io.h b/Triangulation/include/CGAL/IO/Triangulation_io.h index 89c3bc4bd33..7cd5b8ac3f2 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_io.h +++ b/Triangulation/include/CGAL/IO/Triangulation_io.h @@ -33,13 +33,12 @@ std::ostream & operator<<(std::ostream & os, const typename Wrap::Point_d & p) { typename K::Cartesian_const_iterator_d it = p.cartesian_begin(); - os << "(" << *it; + os << *it; ++it; for ( ; it != p.cartesian_end() ; ++it) { - os << ", " << *it; + os << " " << *it; } - os << ")"; return os; } @@ -58,6 +57,90 @@ operator<<(std::ostream & os, const Triangulation_vertex & v) return os; }*/ + +template +std::ostream & +export_triangulation_to_off(std::ostream & os, const Tr & tr) +{ + typedef typename Tr::Vertex_const_handle Vertex_handle; + typedef typename Tr::Vertex_const_iterator Vertex_iterator; + typedef typename Tr::Finite_vertex_const_iterator Finite_vertex_iterator; + typedef typename Tr::Full_cell_const_handle Full_cell_handle; + typedef typename Tr::Finite_full_cell_const_iterator Finite_full_cell_iterator; + typedef typename Tr::Full_cell_const_iterator Full_cell_iterator; + typedef typename Tr::Full_cell Full_cell; + typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator; + + if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3) + { + std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3."; + os << "Warning: export_tds_to_off => dimension should be 2 or 3."; + return os; + } + + size_t n = tr.number_of_vertices(); + + std::stringstream output; + + // write the vertices + std::map index_of_vertex; + int i = 0; + for(Finite_vertex_iterator it = tr.finite_vertices_begin(); + it != tr.finite_vertices_end(); ++it, ++i) + { + output << *it; + if (tr.maximal_dimension() == 2) + output << " 0"; + output << std::endl; + index_of_vertex[it.base()] = i; + } + CGAL_assertion( i == n ); + + size_t number_of_triangles = 0; + if (tr.maximal_dimension() == 2) + { + for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ; + fch != tr.finite_full_cells_end() ; ++fch) + { + output << "3 "; + for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; + vit != fch->vertices_end() ; ++vit) + { + output << index_of_vertex[*vit] << " "; + } + output << std::endl; + ++number_of_triangles; + } + } + else if (tr.maximal_dimension() == 3) + { + // Parse boundary facets + for (Full_cell_iterator fch = tr.full_cells_begin() ; + fch != tr.full_cells_end() ; ++fch) + { + if (tr.is_infinite(fch)) + { + output << "3 "; + for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; + vit != fch->vertices_end() ; ++vit, ++i) + { + if (!tr.is_infinite(*vit)) + output << index_of_vertex[*vit] << " "; + } + output << std::endl; + ++number_of_triangles; + } + } + } + + os << "OFF \n" + << n << " " + << number_of_triangles << " 0\n" + << output.str(); + + return os; +} + } //namespace CGAL #endif // CGAL_TRIANGULATION_IO_H From eebad0e1a4c0d333f8651e4370a9a6247afd1ded Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 16 Jun 2014 19:35:04 +0200 Subject: [PATCH 022/487] Add applications to help comparison between T2/T3 and Td --- .../Triangulation_2/data/points.cin | 10 ++ .../Triangulation_2/points_to_RT2_to_off.cpp | 30 ++++++ .../CGAL/IO/Triangulation_off_ostream_2.h | 79 +++++++++++++++ .../Triangulation_3/data/points.cin | 10 ++ .../Triangulation_3/points_to_RT3_to_off.cpp | 29 ++++++ .../CGAL/IO/Triangulation_off_ostream_3.h | 96 +++++++++++++++++++ 6 files changed, 254 insertions(+) create mode 100644 Triangulation_2/applications/Triangulation_2/data/points.cin create mode 100644 Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp create mode 100644 Triangulation_2/include/CGAL/IO/Triangulation_off_ostream_2.h create mode 100644 Triangulation_3/applications/Triangulation_3/data/points.cin create mode 100644 Triangulation_3/applications/Triangulation_3/points_to_RT3_to_off.cpp create mode 100644 Triangulation_3/include/CGAL/IO/Triangulation_off_ostream_3.h diff --git a/Triangulation_2/applications/Triangulation_2/data/points.cin b/Triangulation_2/applications/Triangulation_2/data/points.cin new file mode 100644 index 00000000000..52e8743d807 --- /dev/null +++ b/Triangulation_2/applications/Triangulation_2/data/points.cin @@ -0,0 +1,10 @@ +0.0071 1.6899 0 +0.3272 1.3694 0.05 +1.3697 1.8296 0.1 +0.6722 0.3012 0.15 +1.1726 0.1899 0.2 +0.4374 2.8541 0.25 +2.5923 0.1904 0.3 +1.3083 2.5462 0.35 +1.4981 1.3929 0.4 +2.1304 2.055 0.45 \ No newline at end of file diff --git a/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp b/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp new file mode 100644 index 00000000000..5cc200ae784 --- /dev/null +++ b/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Regular_triangulation_filtered_traits_2 Traits; +typedef CGAL::Regular_triangulation_2 Regular_triangulation; + +int main() +{ + std::ifstream in("data/points.cin"); + + Regular_triangulation::Weighted_point wp; + int count = 0; + std::vector wpoints; + + while(in >> wp) + { + count++; + wpoints.push_back(wp); + } + Regular_triangulation rt(wpoints.begin(), wpoints.end()); + std::ofstream off_stream("data/rt2.off"); + CGAL::export_triangulation_2_to_off(off_stream, rt); + return 0; +} diff --git a/Triangulation_2/include/CGAL/IO/Triangulation_off_ostream_2.h b/Triangulation_2/include/CGAL/IO/Triangulation_off_ostream_2.h new file mode 100644 index 00000000000..a4cd70e8e0d --- /dev/null +++ b/Triangulation_2/include/CGAL/IO/Triangulation_off_ostream_2.h @@ -0,0 +1,79 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// Author(s) : Clement Jamin + + +#ifndef CGAL_TRIANGULATION_OFF_OSTREAM_2_H +#define CGAL_TRIANGULATION_OFF_OSTREAM_2_H + +#include +#include +#include + +namespace CGAL { + +template < class GT, class TDS > +std::ostream & +export_triangulation_2_to_off(std::ostream & os, + const Triangulation_2 & tr) +{ + typedef Triangulation_2 Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Vertex_iterator Vertex_iterator; + typedef typename Tr::Finite_vertices_iterator Finite_vertex_iterator; + typedef typename Tr::Finite_faces_iterator Finite_faces_iterator; + + size_t n = tr.number_of_vertices(); + + std::stringstream output; + + // write the vertices + std::map index_of_vertex; + int i = 0; + for(Finite_vertex_iterator it = tr.finite_vertices_begin(); + it != tr.finite_vertices_end(); ++it, ++i) + { + output << it->point().x() << " " << it->point().y() << " 0" << std::endl; + index_of_vertex[it.base()] = i; + } + CGAL_assertion( i == n ); + + size_t number_of_triangles = 0; + + for (Finite_faces_iterator fit = tr.finite_faces_begin() ; + fit != tr.finite_faces_end() ; ++fit) + { + output << "3 " + << index_of_vertex[fit->vertex(0)] << " " + << index_of_vertex[fit->vertex(1)] << " " + << index_of_vertex[fit->vertex(2)] + << std::endl; + ++number_of_triangles; + } + + os << "OFF \n" + << n << " " + << number_of_triangles << " 0\n" + << output.str(); + + return os; +} + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_OFF_OSTREAM_2_H \ No newline at end of file diff --git a/Triangulation_3/applications/Triangulation_3/data/points.cin b/Triangulation_3/applications/Triangulation_3/data/points.cin new file mode 100644 index 00000000000..5f2f53d1426 --- /dev/null +++ b/Triangulation_3/applications/Triangulation_3/data/points.cin @@ -0,0 +1,10 @@ +0.0071 1.6899 2.521 0 +0.3272 1.3694 3.15 0.05 +1.3697 1.8296 2.654 0.1 +0.6722 0.3012 0.1548 0.15 +1.1726 0.1899 0.3658 0.2 +0.4374 2.8541 1.45894 0.25 +2.5923 0.1904 0.6971 0.3 +1.3083 2.5462 1.3658 0.35 +1.4981 1.3929 2.949 0.4 +2.1304 2.055 0.6597455 0.45 \ No newline at end of file diff --git a/Triangulation_3/applications/Triangulation_3/points_to_RT3_to_off.cpp b/Triangulation_3/applications/Triangulation_3/points_to_RT3_to_off.cpp new file mode 100644 index 00000000000..6bdb37ef1a1 --- /dev/null +++ b/Triangulation_3/applications/Triangulation_3/points_to_RT3_to_off.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Regular_triangulation_euclidean_traits_3 Traits; +typedef CGAL::Regular_triangulation_3 Regular_triangulation; + +int main() +{ + std::ifstream in("data/points.cin"); + + Regular_triangulation::Weighted_point wp; + int count = 0; + std::vector wpoints; + + while(in >> wp) + { + count++; + wpoints.push_back(wp); + } + Regular_triangulation rt(wpoints.begin(), wpoints.end()); + std::ofstream off_stream("data/rt3.off"); + CGAL::export_triangulation_3_to_off(off_stream, rt); + return 0; +} diff --git a/Triangulation_3/include/CGAL/IO/Triangulation_off_ostream_3.h b/Triangulation_3/include/CGAL/IO/Triangulation_off_ostream_3.h new file mode 100644 index 00000000000..f55d89ddf87 --- /dev/null +++ b/Triangulation_3/include/CGAL/IO/Triangulation_off_ostream_3.h @@ -0,0 +1,96 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// Author(s) : Clement Jamin + + +#ifndef CGAL_TRIANGULATION_OFF_OSTREAM_3_H +#define CGAL_TRIANGULATION_OFF_OSTREAM_3_H + +#include +#include +#include + +namespace CGAL { + +template < class GT, class TDS > +std::ostream & +export_triangulation_3_to_off(std::ostream & os, + const Triangulation_3 & tr) +{ + typedef Triangulation_3 Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Vertex_iterator Vertex_iterator; + typedef typename Tr::Finite_vertices_iterator Finite_vertex_iterator; + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + + size_t n = tr.number_of_vertices(); + + std::stringstream output; + + // write the vertices + std::map index_of_vertex; + int i = 0; + for(Finite_vertex_iterator it = tr.finite_vertices_begin(); + it != tr.finite_vertices_end(); ++it, ++i) + { + output << it->point().x() << " " + << it->point().y() << " " + << it->point().z() << std::endl; + index_of_vertex[it.base()] = i; + } + CGAL_assertion( i == n ); + + size_t number_of_triangles = 0; + + for (Finite_cells_iterator cit = tr.finite_cells_begin() ; + cit != tr.finite_cells_end() ; ++cit) + { + output << "3 " + << index_of_vertex[cit->vertex(0)] << " " + << index_of_vertex[cit->vertex(1)] << " " + << index_of_vertex[cit->vertex(2)] + << std::endl; + output << "3 " + << index_of_vertex[cit->vertex(0)] << " " + << index_of_vertex[cit->vertex(2)] << " " + << index_of_vertex[cit->vertex(3)] + << std::endl; + output << "3 " + << index_of_vertex[cit->vertex(1)] << " " + << index_of_vertex[cit->vertex(2)] << " " + << index_of_vertex[cit->vertex(3)] + << std::endl; + output << "3 " + << index_of_vertex[cit->vertex(0)] << " " + << index_of_vertex[cit->vertex(1)] << " " + << index_of_vertex[cit->vertex(3)] + << std::endl; + ++number_of_triangles; + } + + os << "OFF \n" + << n << " " + << number_of_triangles << " 0\n" + << output.str(); + + return os; +} + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_OFF_OSTREAM_3_H \ No newline at end of file From de6fbd8d8568d0a32dd8d9d8bbd4c96980f0e974 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 00:17:05 +0200 Subject: [PATCH 023/487] Triangulation_io.h does not exist anymore --- Triangulation/test/Triangulation/delaunay.cpp | 3 --- Triangulation/test/Triangulation/regular.cpp | 5 +---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Triangulation/test/Triangulation/delaunay.cpp b/Triangulation/test/Triangulation/delaunay.cpp index 3a0dad37f07..13ab4f97cc8 100644 --- a/Triangulation/test/Triangulation/delaunay.cpp +++ b/Triangulation/test/Triangulation/delaunay.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -94,8 +93,6 @@ void test(const int d, const string & type, const int N) cout << "\nThere are " << cells.size() << " vertices on the convex hull."; cells.clear(); } - - cout << dt.tds() << std::endl; // Remove all ! cerr << "\nBefore removal: " << dt.number_of_vertices() << " vertices. After: "; diff --git a/Triangulation/test/Triangulation/regular.cpp b/Triangulation/test/Triangulation/regular.cpp index 1956651c682..8b6198dad8e 100644 --- a/Triangulation/test/Triangulation/regular.cpp +++ b/Triangulation/test/Triangulation/regular.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -46,7 +45,7 @@ void test(const int d, const string & type, const int N) coords[j] = static_cast(rand() % 100000)/10000; points.push_back(Point( Bare_point(d, coords.begin(), coords.end()), - static_cast(rand() % 100000)/100000 + /*static_cast(rand() % 100000)/100000*/static_cast(i)/20 )); } rt.insert(points.begin(), points.end()); @@ -94,8 +93,6 @@ void test(const int d, const string & type, const int N) cells.clear(); } - cout << rt.tds() << std::endl; - // Remove all ! cerr << "\nBefore removal: " << rt.number_of_vertices() << " vertices. After: "; random_shuffle(points.begin(), points.end()); From 3898ccdd8bd218eeeb51188a1f741d8d3aaa5651 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 00:17:51 +0200 Subject: [PATCH 024/487] Remove Triangulation_io.h --- .../include/CGAL/IO/Triangulation_io.h | 146 ------------------ 1 file changed, 146 deletions(-) delete mode 100644 Triangulation/include/CGAL/IO/Triangulation_io.h diff --git a/Triangulation/include/CGAL/IO/Triangulation_io.h b/Triangulation/include/CGAL/IO/Triangulation_io.h deleted file mode 100644 index 7cd5b8ac3f2..00000000000 --- a/Triangulation/include/CGAL/IO/Triangulation_io.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2014 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org); you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 3 of the License, -// or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL: $ -// $Id: $ -// -// Author(s) : Clement Jamin - - -#ifndef CGAL_TRIANGULATION_IO_H -#define CGAL_TRIANGULATION_IO_H - -#include -#include -#include -#include - -namespace CGAL { - -template -std::ostream & -operator<<(std::ostream & os, const typename Wrap::Point_d & p) -{ - typename K::Cartesian_const_iterator_d it = p.cartesian_begin(); - os << *it; - ++it; - for ( ; it != p.cartesian_end() ; ++it) - { - os << " " << *it; - } - return os; -} - -template -std::ostream & -operator<<(std::ostream & os, const typename Wrap::Weighted_point_d & p) -{ - return os << p.point(); -} - -/*template< class A, class B > -std::ostream & -operator<<(std::ostream & os, const Triangulation_vertex & v) -{ - os << v.point(); - return os; -}*/ - - -template -std::ostream & -export_triangulation_to_off(std::ostream & os, const Tr & tr) -{ - typedef typename Tr::Vertex_const_handle Vertex_handle; - typedef typename Tr::Vertex_const_iterator Vertex_iterator; - typedef typename Tr::Finite_vertex_const_iterator Finite_vertex_iterator; - typedef typename Tr::Full_cell_const_handle Full_cell_handle; - typedef typename Tr::Finite_full_cell_const_iterator Finite_full_cell_iterator; - typedef typename Tr::Full_cell_const_iterator Full_cell_iterator; - typedef typename Tr::Full_cell Full_cell; - typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator; - - if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3) - { - std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3."; - os << "Warning: export_tds_to_off => dimension should be 2 or 3."; - return os; - } - - size_t n = tr.number_of_vertices(); - - std::stringstream output; - - // write the vertices - std::map index_of_vertex; - int i = 0; - for(Finite_vertex_iterator it = tr.finite_vertices_begin(); - it != tr.finite_vertices_end(); ++it, ++i) - { - output << *it; - if (tr.maximal_dimension() == 2) - output << " 0"; - output << std::endl; - index_of_vertex[it.base()] = i; - } - CGAL_assertion( i == n ); - - size_t number_of_triangles = 0; - if (tr.maximal_dimension() == 2) - { - for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ; - fch != tr.finite_full_cells_end() ; ++fch) - { - output << "3 "; - for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; - vit != fch->vertices_end() ; ++vit) - { - output << index_of_vertex[*vit] << " "; - } - output << std::endl; - ++number_of_triangles; - } - } - else if (tr.maximal_dimension() == 3) - { - // Parse boundary facets - for (Full_cell_iterator fch = tr.full_cells_begin() ; - fch != tr.full_cells_end() ; ++fch) - { - if (tr.is_infinite(fch)) - { - output << "3 "; - for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; - vit != fch->vertices_end() ; ++vit, ++i) - { - if (!tr.is_infinite(*vit)) - output << index_of_vertex[*vit] << " "; - } - output << std::endl; - ++number_of_triangles; - } - } - } - - os << "OFF \n" - << n << " " - << number_of_triangles << " 0\n" - << output.str(); - - return os; -} - -} //namespace CGAL - -#endif // CGAL_TRIANGULATION_IO_H From 2f4c40cdad84ac8fbab7c6d7b335fc9ff50ca666 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 00:18:34 +0200 Subject: [PATCH 025/487] Fix a warning --- Triangulation/include/CGAL/Triangulation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 8d90a185bbf..7984f3ca17d 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -257,8 +257,8 @@ public: : tds_(dim) , kernel_(k) , infinity_() - , rng_((long)0) , preset_flat_orientation_(std::numeric_limits::max(), NULL) + , rng_((long)0) #ifdef CGAL_TRIANGULATION_STATISTICS ,walk_size_(0) #endif @@ -278,8 +278,8 @@ public: : tds_(dim) , kernel_(k) , infinity_() - , rng_((long)0) , preset_flat_orientation_(preset_flat_orientation) + , rng_((long)0) #ifdef CGAL_TRIANGULATION_STATISTICS ,walk_size_(0) #endif @@ -291,8 +291,8 @@ public: : tds_(t2.tds_) , kernel_(t2.kernel_) , infinity_() - , rng_(t2.rng_) , preset_flat_orientation_(std::numeric_limits::max(), NULL) + , rng_(t2.rng_) #ifdef CGAL_TRIANGULATION_STATISTICS ,walk_size_(t2.walk_size_) #endif From 60fc6b63f381dbf74bab2ead1ef61fc55721e570 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 11:23:12 +0200 Subject: [PATCH 026/487] RTd to OFF application --- .../Triangulation/data/points.cin | 11 + .../Triangulation/points_to_RT_to_off.cpp | 30 +++ .../CGAL/IO/Triangulation_off_ostream.h | 194 ++++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 Triangulation/applications/Triangulation/data/points.cin create mode 100644 Triangulation/applications/Triangulation/points_to_RT_to_off.cpp create mode 100644 Triangulation/include/CGAL/IO/Triangulation_off_ostream.h diff --git a/Triangulation/applications/Triangulation/data/points.cin b/Triangulation/applications/Triangulation/data/points.cin new file mode 100644 index 00000000000..68477fd5d57 --- /dev/null +++ b/Triangulation/applications/Triangulation/data/points.cin @@ -0,0 +1,11 @@ +2 +0.0071 1.6899 1.2 0 +0.3272 1.3694 0.05 +1.3697 1.8296 0.1 +0.6722 0.3012 0.15 +1.1726 0.1899 0.2 +0.4374 2.8541 0.25 +2.5923 0.1904 0.3 +1.3083 2.5462 0.35 +1.4981 1.3929 0.4 +2.1304 2.055 0.45 \ No newline at end of file diff --git a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp new file mode 100644 index 00000000000..f35d94ced4d --- /dev/null +++ b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +#include + +typedef CGAL::Epick_d K; +typedef CGAL::Regular_triangulation_euclidean_traits Traits; +typedef CGAL::Regular_triangulation RT; + +int main() +{ + std::ifstream in("data/points.cin"); + + RT::Weighted_point wp; + std::vector wpoints; + + int dim; + in >> dim; + while(in >> wp) + wpoints.push_back(wp); + + // Build the Regular Triangulation + RT rt(dim); + rt.insert(wpoints.begin(), wpoints.end()); + std::ofstream off_stream("data/rt.off"); + CGAL::export_triangulation_to_off(off_stream, rt); + return 0; +} diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h new file mode 100644 index 00000000000..d28e54a8a6c --- /dev/null +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -0,0 +1,194 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// Author(s) : Clement Jamin + + +#ifndef CGAL_TRIANGULATION_IO_H +#define CGAL_TRIANGULATION_IO_H + +#include +#include +#include +#include + +namespace CGAL { + +template +std::ostream & +operator<<(std::ostream & os, const typename Wrap::Point_d & p) +{ + typename K::Cartesian_const_iterator_d it = p.cartesian_begin(); + os << *it; + ++it; + for ( ; it != p.cartesian_end() ; ++it) + { + os << " " << *it; + } + return os; +} + +template +std::ostream & +operator<<(std::ostream & os, const typename Wrap::Weighted_point_d & p) +{ + return os << p.point(); +} + + +template +std::istream & +operator>>(std::istream &is, typename Wrap::Point_d & p) +{ + typedef typename Wrap::Point_d P; + typedef typename K::FT FT; + std::vector coords; + + std::string line; + for(;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + while (line_sstr >> temp) + coords.push_back(temp); + + p = P(coords.begin(), coords.end()); + return is; +} + +template +std::istream & +operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) +{ + typedef typename Wrap::Point_d P; + typedef typename Wrap::Weighted_point_d WP; + typedef typename K::FT FT; + + std::string line; + for(;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + std::vector coords; + while (line_sstr >> temp) + coords.push_back(temp); + + std::vector::iterator last = coords.end() - 1; + P p = P(coords.begin(), last); + wp = WP(p, *last); + + return is; +} + +template < class GT, class TDS > +std::ostream & +export_triangulation_to_off(std::ostream & os, + const Triangulation & tr) +{ + typedef Triangulation Tr; + typedef typename Tr::Vertex_const_handle Vertex_handle; + typedef typename Tr::Vertex_const_iterator Vertex_iterator; + typedef typename Tr::Finite_vertex_const_iterator Finite_vertex_iterator; + typedef typename Tr::Full_cell_const_handle Full_cell_handle; + typedef typename Tr::Finite_full_cell_const_iterator Finite_full_cell_iterator; + typedef typename Tr::Full_cell_const_iterator Full_cell_iterator; + typedef typename Tr::Full_cell Full_cell; + typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator; + + if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3) + { + std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3."; + os << "Warning: export_tds_to_off => dimension should be 2 or 3."; + return os; + } + + size_t n = tr.number_of_vertices(); + + std::stringstream output; + + // write the vertices + std::map index_of_vertex; + int i = 0; + for(Finite_vertex_iterator it = tr.finite_vertices_begin(); + it != tr.finite_vertices_end(); ++it, ++i) + { + output << *it; + if (tr.maximal_dimension() == 2) + output << " 0"; + output << std::endl; + index_of_vertex[it.base()] = i; + } + CGAL_assertion( i == n ); + + size_t number_of_triangles = 0; + if (tr.maximal_dimension() == 2) + { + for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ; + fch != tr.finite_full_cells_end() ; ++fch) + { + output << "3 "; + for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; + vit != fch->vertices_end() ; ++vit) + { + output << index_of_vertex[*vit] << " "; + } + output << std::endl; + ++number_of_triangles; + } + } + else if (tr.maximal_dimension() == 3) + { + // Parse boundary facets + for (Full_cell_iterator fch = tr.full_cells_begin() ; + fch != tr.full_cells_end() ; ++fch) + { + if (tr.is_infinite(fch)) + { + output << "3 "; + for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; + vit != fch->vertices_end() ; ++vit, ++i) + { + if (!tr.is_infinite(*vit)) + output << index_of_vertex[*vit] << " "; + } + output << std::endl; + ++number_of_triangles; + } + } + } + + os << "OFF \n" + << n << " " + << number_of_triangles << " 0\n" + << output.str(); + + return os; +} + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_IO_H From ad12bb88df00be49ce4a1d71f3c7f242f5af60c3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 11:23:33 +0200 Subject: [PATCH 027/487] Fix MSVC warnings --- Triangulation/include/CGAL/Triangulation_full_cell.h | 2 +- Triangulation/include/CGAL/Triangulation_vertex.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation_full_cell.h b/Triangulation/include/CGAL/Triangulation_full_cell.h index 6238278370a..c38d060eeba 100644 --- a/Triangulation/include/CGAL/Triangulation_full_cell.h +++ b/Triangulation/include/CGAL/Triangulation_full_cell.h @@ -126,7 +126,7 @@ operator>>(std::istream & is, No_full_cell_data &) } std::ostream & -operator<<(std::ostream & os, const No_full_cell_data & nd) +operator<<(std::ostream & os, const No_full_cell_data &) { return os; } diff --git a/Triangulation/include/CGAL/Triangulation_vertex.h b/Triangulation/include/CGAL/Triangulation_vertex.h index 8590919e07f..36e4d0591a0 100644 --- a/Triangulation/include/CGAL/Triangulation_vertex.h +++ b/Triangulation/include/CGAL/Triangulation_vertex.h @@ -98,7 +98,7 @@ operator>>(std::istream & is, No_vertex_data &) } std::ostream & -operator<<(std::ostream & os, const No_vertex_data & nd) +operator<<(std::ostream & os, const No_vertex_data &) { return os; } From d8b0e2904e1e37be64a408e66e358d20178e0a1b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 14:48:03 +0200 Subject: [PATCH 028/487] New data for 2D and 3D + improved export --- .../data/{points.cin => points_2.cin} | 6 +- .../Triangulation/data/points_3.cin | 11 ++++ .../Triangulation/points_to_RT_to_off.cpp | 26 ++++++--- .../CGAL/IO/Triangulation_off_ostream.h | 57 +++++++++++++++---- 4 files changed, 78 insertions(+), 22 deletions(-) rename Triangulation/applications/Triangulation/data/{points.cin => points_2.cin} (59%) create mode 100644 Triangulation/applications/Triangulation/data/points_3.cin diff --git a/Triangulation/applications/Triangulation/data/points.cin b/Triangulation/applications/Triangulation/data/points_2.cin similarity index 59% rename from Triangulation/applications/Triangulation/data/points.cin rename to Triangulation/applications/Triangulation/data/points_2.cin index 68477fd5d57..19b563f4835 100644 --- a/Triangulation/applications/Triangulation/data/points.cin +++ b/Triangulation/applications/Triangulation/data/points_2.cin @@ -1,11 +1,11 @@ 2 -0.0071 1.6899 1.2 0 +0.0071 1.6899 0 0.3272 1.3694 0.05 1.3697 1.8296 0.1 0.6722 0.3012 0.15 1.1726 0.1899 0.2 -0.4374 2.8541 0.25 +0.4374 2.8541 100.25 2.5923 0.1904 0.3 -1.3083 2.5462 0.35 +1.3083 2.5462 200.35 1.4981 1.3929 0.4 2.1304 2.055 0.45 \ No newline at end of file diff --git a/Triangulation/applications/Triangulation/data/points_3.cin b/Triangulation/applications/Triangulation/data/points_3.cin new file mode 100644 index 00000000000..5ffbc05d517 --- /dev/null +++ b/Triangulation/applications/Triangulation/data/points_3.cin @@ -0,0 +1,11 @@ +3 +0.0071 1.6899 2.521 0 +0.3272 1.3694 3.15 100.05 +1.3697 1.8296 2.654 0.1 +0.6722 0.3012 0.1548 100.15 +1.1726 0.1899 0.3658 0.2 +0.4374 2.8541 1.45894 200.25 +2.5923 0.1904 0.6971 0.3 +1.3083 2.5462 1.3658 100.35 +1.4981 1.3929 2.949 0.4 +2.1304 2.055 0.6597455 1.45 \ No newline at end of file diff --git a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp index f35d94ced4d..3c227738ed7 100644 --- a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp +++ b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp @@ -9,22 +9,34 @@ typedef CGAL::Epick_d K; typedef CGAL::Regular_triangulation_euclidean_traits Traits; typedef CGAL::Regular_triangulation RT; -int main() +void test(int dim) { - std::ifstream in("data/points.cin"); + std::stringstream input_filename; + input_filename << "data/points_" << dim << ".cin"; + std::ifstream in(input_filename.str()); RT::Weighted_point wp; std::vector wpoints; - int dim; - in >> dim; + int dim_from_file; + in >> dim_from_file; while(in >> wp) wpoints.push_back(wp); // Build the Regular Triangulation - RT rt(dim); + RT rt(dim_from_file); rt.insert(wpoints.begin(), wpoints.end()); - std::ofstream off_stream("data/rt.off"); - CGAL::export_triangulation_to_off(off_stream, rt); + + // Export + std::stringstream output_filename; + output_filename << "data/rt_dim" << dim << ".off"; + std::ofstream off_stream(output_filename.str()); + CGAL::export_triangulation_to_off(off_stream, rt, false); +} + +int main() +{ + test(2); + test(3); return 0; } diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index d28e54a8a6c..9f40181db6c 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -107,7 +107,8 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) template < class GT, class TDS > std::ostream & export_triangulation_to_off(std::ostream & os, - const Triangulation & tr) + const Triangulation & tr, + bool in_3D_export_surface_only = true) { typedef Triangulation Tr; typedef typename Tr::Vertex_const_handle Vertex_handle; @@ -162,21 +163,53 @@ export_triangulation_to_off(std::ostream & os, } else if (tr.maximal_dimension() == 3) { - // Parse boundary facets - for (Full_cell_iterator fch = tr.full_cells_begin() ; - fch != tr.full_cells_end() ; ++fch) + if (in_3D_export_surface_only) { - if (tr.is_infinite(fch)) + // Parse boundary facets + for (Full_cell_iterator fch = tr.full_cells_begin() ; + fch != tr.full_cells_end() ; ++fch) { - output << "3 "; - for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; - vit != fch->vertices_end() ; ++vit, ++i) + if (tr.is_infinite(fch)) { - if (!tr.is_infinite(*vit)) - output << index_of_vertex[*vit] << " "; + output << "3 "; + for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; + vit != fch->vertices_end() ; ++vit) + { + if (!tr.is_infinite(*vit)) + output << index_of_vertex[*vit] << " "; + } + output << std::endl; + ++number_of_triangles; } - output << std::endl; - ++number_of_triangles; + } + } + else + { + // Parse boundary facets + for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ; + fch != tr.finite_full_cells_end() ; ++fch) + { + output << "3 " + << index_of_vertex[fch->vertex(0)] << " " + << index_of_vertex[fch->vertex(1)] << " " + << index_of_vertex[fch->vertex(2)] + << std::endl; + output << "3 " + << index_of_vertex[fch->vertex(0)] << " " + << index_of_vertex[fch->vertex(2)] << " " + << index_of_vertex[fch->vertex(3)] + << std::endl; + output << "3 " + << index_of_vertex[fch->vertex(1)] << " " + << index_of_vertex[fch->vertex(2)] << " " + << index_of_vertex[fch->vertex(3)] + << std::endl; + output << "3 " + << index_of_vertex[fch->vertex(0)] << " " + << index_of_vertex[fch->vertex(1)] << " " + << index_of_vertex[fch->vertex(3)] + << std::endl; + number_of_triangles += 4; } } } From 54ab0fc5a126b936e2309ace5187dd041a70283a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 14:48:34 +0200 Subject: [PATCH 029/487] Clean-up debug traces --- .../CGAL/NewKernel_d/KernelD_converter.h | 23 +------------------ .../include/CGAL/Regular_triangulation.h | 1 - .../Regular_triangulation_euclidean_traits.h | 4 ---- Triangulation/include/CGAL/Triangulation.h | 4 ---- 4 files changed, 1 insertion(+), 31 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h b/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h index 382e2cb92f5..b58630344e7 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/KernelD_converter.h @@ -93,23 +93,7 @@ class KernelD_converter_ //typedef typename KOC::argument_type K1_Obj; //typedef typename KOC::result_type K2_Obj; public: -#if defined(BOOST_MSVC) - void disp(const std::array &o) const // CJTODO DEBUG - { - std::cerr << o[0] << " (std::array)"; - } -#else - void disp(const cpp11::array &o) const // CJTODO DEBUG - { - std::cerr << o[0] << " (cpp11::array)"; - } -#endif - template - void disp(const P &o) const // CJTODO DEBUG - { - std::cerr << o.point()[0] << " (Point)"; - } - using Base::operator(); // don't use directly, just make it accessible to the next level + using Base::operator(); // don't use directly, just make it accessible to the next level K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD true_type)const{ return KOC()(this->myself().kernel(),this->myself().kernel2(),this->myself(),o); } @@ -117,11 +101,6 @@ class KernelD_converter_ return K1_Conv(this->myself().kernel())(this->myself().kernel2(),this->myself(),o); } K2_Obj operator()(argument_type const& o)const{ - /*std::cerr << "KernelD_converter_::operator() "; // CJTODO DEBUG - disp(o); - std::cerr << std::endl;*/ - //K2_Obj k2o = helper(o,no_converter()); - //disp(k2o); return helper(o,no_converter()); } template struct result:Base::template result{}; diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index b736392cbf6..f40f1c55bc5 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -229,7 +229,6 @@ public: Locate_type lt; Face f(maximal_dimension()); Facet ft; - std::cerr << "Inserting " << p->point()[0] << " " << p->point()[1] << std::endl; Full_cell_handle c = locate (*p, lt, f, ft, hint); Vertex_handle v = insert (*p, lt, f, ft, c); diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 30ad449d967..e13cd57a5ed 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -94,10 +94,6 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - /*std::cerr << "Traits flat orientation - points: " ; // CJTODO DEBUG - for (ForwardIterator it = start ; it != end ; ++it) - std::cerr << (*it).point()[0] << " "; - std::cerr << std::endl; // CJTODO DEBUG*/ Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.construct_flat_orientation_d_object() ( boost::make_transform_iterator(start, pdw), diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 7984f3ca17d..d71bc89ae37 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -594,10 +594,6 @@ public: } else { - /*std::cerr << "orientation points: " ; // CJTODO DEBUG - for (auto it = points_begin(s) ; it != points_begin(s) + 1 + current_dimension() ; ++it) - std::cerr << (*it).point()[0] << " "; - std::cerr << std::endl; // CJTODO DEBUG*/ return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); } } From 5ae8464a8171bcbed91799ef8eabb1d612ba6472 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 14:51:31 +0200 Subject: [PATCH 030/487] Code clean-up (unused variable) --- .../applications/Triangulation_2/points_to_RT2_to_off.cpp | 5 +---- .../applications/Triangulation_3/points_to_RT3_to_off.cpp | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp b/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp index 5cc200ae784..f7a18fb81cb 100644 --- a/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp +++ b/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp @@ -15,14 +15,11 @@ int main() std::ifstream in("data/points.cin"); Regular_triangulation::Weighted_point wp; - int count = 0; std::vector wpoints; while(in >> wp) - { - count++; wpoints.push_back(wp); - } + Regular_triangulation rt(wpoints.begin(), wpoints.end()); std::ofstream off_stream("data/rt2.off"); CGAL::export_triangulation_2_to_off(off_stream, rt); diff --git a/Triangulation_3/applications/Triangulation_3/points_to_RT3_to_off.cpp b/Triangulation_3/applications/Triangulation_3/points_to_RT3_to_off.cpp index 6bdb37ef1a1..4dffb3ea265 100644 --- a/Triangulation_3/applications/Triangulation_3/points_to_RT3_to_off.cpp +++ b/Triangulation_3/applications/Triangulation_3/points_to_RT3_to_off.cpp @@ -14,14 +14,11 @@ int main() std::ifstream in("data/points.cin"); Regular_triangulation::Weighted_point wp; - int count = 0; std::vector wpoints; while(in >> wp) - { - count++; wpoints.push_back(wp); - } + Regular_triangulation rt(wpoints.begin(), wpoints.end()); std::ofstream off_stream("data/rt3.off"); CGAL::export_triangulation_3_to_off(off_stream, rt); From 754808bef77998664c8cfd64b9b4670814fa1f1d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 14:53:10 +0200 Subject: [PATCH 031/487] Change default param value (for export) --- .../applications/Triangulation/points_to_RT_to_off.cpp | 2 +- Triangulation/include/CGAL/IO/Triangulation_off_ostream.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp index 3c227738ed7..4598c012360 100644 --- a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp +++ b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp @@ -31,7 +31,7 @@ void test(int dim) std::stringstream output_filename; output_filename << "data/rt_dim" << dim << ".off"; std::ofstream off_stream(output_filename.str()); - CGAL::export_triangulation_to_off(off_stream, rt, false); + CGAL::export_triangulation_to_off(off_stream, rt); } int main() diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 9f40181db6c..a58be847576 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -108,7 +108,7 @@ template < class GT, class TDS > std::ostream & export_triangulation_to_off(std::ostream & os, const Triangulation & tr, - bool in_3D_export_surface_only = true) + bool in_3D_export_surface_only = false) { typedef Triangulation Tr; typedef typename Tr::Vertex_const_handle Vertex_handle; From 30e47d01a1edbc3baa2c3a87562e0629ea9e15ae Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 14:54:10 +0200 Subject: [PATCH 032/487] Added the ability to export the surface --- .../CGAL/IO/Triangulation_off_ostream_3.h | 71 ++++++++++++------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/Triangulation_3/include/CGAL/IO/Triangulation_off_ostream_3.h b/Triangulation_3/include/CGAL/IO/Triangulation_off_ostream_3.h index f55d89ddf87..b6287f71d52 100644 --- a/Triangulation_3/include/CGAL/IO/Triangulation_off_ostream_3.h +++ b/Triangulation_3/include/CGAL/IO/Triangulation_off_ostream_3.h @@ -30,12 +30,14 @@ namespace CGAL { template < class GT, class TDS > std::ostream & export_triangulation_3_to_off(std::ostream & os, - const Triangulation_3 & tr) + const Triangulation_3 & tr, + bool export_surface_only = false) { typedef Triangulation_3 Tr; typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Vertex_iterator Vertex_iterator; typedef typename Tr::Finite_vertices_iterator Finite_vertex_iterator; + typedef typename Tr::All_cells_iterator Cells_iterator; typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; size_t n = tr.number_of_vertices(); @@ -57,30 +59,51 @@ export_triangulation_3_to_off(std::ostream & os, size_t number_of_triangles = 0; - for (Finite_cells_iterator cit = tr.finite_cells_begin() ; - cit != tr.finite_cells_end() ; ++cit) + if (export_surface_only) { - output << "3 " - << index_of_vertex[cit->vertex(0)] << " " - << index_of_vertex[cit->vertex(1)] << " " - << index_of_vertex[cit->vertex(2)] - << std::endl; - output << "3 " - << index_of_vertex[cit->vertex(0)] << " " - << index_of_vertex[cit->vertex(2)] << " " - << index_of_vertex[cit->vertex(3)] - << std::endl; - output << "3 " - << index_of_vertex[cit->vertex(1)] << " " - << index_of_vertex[cit->vertex(2)] << " " - << index_of_vertex[cit->vertex(3)] - << std::endl; - output << "3 " - << index_of_vertex[cit->vertex(0)] << " " - << index_of_vertex[cit->vertex(1)] << " " - << index_of_vertex[cit->vertex(3)] - << std::endl; - ++number_of_triangles; + for (Cells_iterator cit = tr.cells_begin() ; + cit != tr.cells_end() ; ++cit) + { + if (tr.is_infinite(cit)) + { + output << "3 "; + for (int i = 0 ; i < 4 ; ++i) + { + if (!tr.is_infinite(cit->vertex(i))) + output << index_of_vertex[cit->vertex(i)] << " "; + } + output << std::endl; + ++number_of_triangles; + } + } + } + else + { + for (Finite_cells_iterator cit = tr.finite_cells_begin() ; + cit != tr.finite_cells_end() ; ++cit) + { + output << "3 " + << index_of_vertex[cit->vertex(0)] << " " + << index_of_vertex[cit->vertex(1)] << " " + << index_of_vertex[cit->vertex(2)] + << std::endl; + output << "3 " + << index_of_vertex[cit->vertex(0)] << " " + << index_of_vertex[cit->vertex(2)] << " " + << index_of_vertex[cit->vertex(3)] + << std::endl; + output << "3 " + << index_of_vertex[cit->vertex(1)] << " " + << index_of_vertex[cit->vertex(2)] << " " + << index_of_vertex[cit->vertex(3)] + << std::endl; + output << "3 " + << index_of_vertex[cit->vertex(0)] << " " + << index_of_vertex[cit->vertex(1)] << " " + << index_of_vertex[cit->vertex(3)] + << std::endl; + number_of_triangles += 4; + } } os << "OFF \n" From 490adcdd1b3aec5a85badce2b8df3a802c100cae Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 17:36:41 +0200 Subject: [PATCH 033/487] Add DT::is_valid and RT::is_valid --- .../include/CGAL/Delaunay_triangulation.h | 48 ++++++++++++++++++- .../include/CGAL/Regular_triangulation.h | 46 +++++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index ba8702c8ae7..d00c3a46ac8 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -103,7 +103,6 @@ public: using Base::insert_in_hole; using Base::insert_outside_convex_hull_1; using Base::is_infinite; - using Base::is_valid; using Base::locate; using Base::points_begin; using Base::set_neighbors; @@ -317,6 +316,10 @@ public: return pred_(dc_.full_cell(f)->neighbor(dc_.index_of_covertex(f))); } }; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + + bool is_valid(bool verbose = false, int level = 0) const; private: // Some internal types to shorten notation @@ -734,7 +737,6 @@ Delaunay_triangulation ::insert_in_conflicting_cell(const Point & p, const Full_cell_handle s) { typedef std::vector Full_cell_h_vector; - typedef typename Full_cell_h_vector::iterator SHV_iterator; static Full_cell_h_vector cs; // for storing conflicting full_cells. cs.clear(); // cs.reserve(64); @@ -845,6 +847,48 @@ Delaunay_triangulation } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + +template< typename DCTraits, typename TDS > +bool +Delaunay_triangulation +::is_valid(bool verbose, int level) const +{ + if (!Base::is_valid(verbose, level)) + return false; + + int dim = current_dimension(); + if (dim == maximal_dimension()) + { + for (Finite_full_cell_const_iterator cit = finite_full_cells_begin() ; + cit != finite_full_cells_end() ; ++cit ) + { + Full_cell_const_handle ch = cit.base(); + for(int i = 0; i < dim+1 ; ++i ) + { + // If the i-th neighbor is not an infinite cell + Vertex_handle opposite_vh = + ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); + if (!is_infinite(opposite_vh)) + { + Side_of_oriented_sphere_d side = + geom_traits().side_of_oriented_sphere_d_object(); + if (side(Point_const_iterator(ch->vertices_begin()), + Point_const_iterator(ch->vertices_end()), + opposite_vh->point()) == ON_BOUNDED_SIDE) + { + if (verbose) + CGAL_warning_msg(false, "Non-empty sphere"); + return false; + } + } + } + } + } + return true; +} + + } //namespace CGAL #endif // CGAL_DELAUNAY_COMPLEX_H diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index f40f1c55bc5..b173136ef65 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -106,7 +106,6 @@ public: using Base::insert_in_hole; using Base::insert_outside_convex_hull_1; using Base::is_infinite; - using Base::is_valid; using Base::locate; using Base::points_begin; using Base::set_neighbors; @@ -340,6 +339,10 @@ public: return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f))); } }; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + + bool is_valid(bool verbose = false, int level = 0) const; private: // Some internal types to shorten notation @@ -883,6 +886,47 @@ Regular_triangulation } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + +template< typename RTTraits, typename TDS > +bool +Regular_triangulation +::is_valid(bool verbose, int level) const +{ + if (!Base::is_valid(verbose, level)) + return false; + + int dim = current_dimension(); + if (dim == maximal_dimension()) + { + for (Finite_full_cell_const_iterator cit = finite_full_cells_begin() ; + cit != finite_full_cells_end() ; ++cit ) + { + Full_cell_const_handle ch = cit.base(); + for(int i = 0; i < dim+1 ; ++i ) + { + // If the i-th neighbor is not an infinite cell + Vertex_handle opposite_vh = + ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); + if (!is_infinite(opposite_vh)) + { + Power_test_d side = + geom_traits().power_test_d_object(); + if (side(Point_const_iterator(ch->vertices_begin()), + Point_const_iterator(ch->vertices_end()), + opposite_vh->point()) == ON_BOUNDED_SIDE) + { + if (verbose) + CGAL_warning_msg(false, "Non-empty sphere"); + return false; + } + } + } + } + } + return true; +} + } //namespace CGAL #endif //CGAL_REGULAR_TRIANGULATION_H From 8926a565d0d7cd61c8ce25dd61379f06315940ae Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 17:37:24 +0200 Subject: [PATCH 034/487] Call is_valid --- Triangulation/applications/Triangulation/points_to_RT_to_off.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp index 4598c012360..94a633a505d 100644 --- a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp +++ b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp @@ -26,6 +26,7 @@ void test(int dim) // Build the Regular Triangulation RT rt(dim_from_file); rt.insert(wpoints.begin(), wpoints.end()); + CGAL_assertion(rt.is_valid(true)); // Export std::stringstream output_filename; From cb848a4375ce493c7af4c710be3da87679b7cbfe Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 17:38:03 +0200 Subject: [PATCH 035/487] Remove useless typedefs --- Triangulation/include/CGAL/Triangulation.h | 5 ----- Triangulation/include/CGAL/Triangulation_data_structure.h | 5 ----- Triangulation/test/Triangulation/delaunay.cpp | 5 ----- 3 files changed, 15 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index d71bc89ae37..3a0cda2631b 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -1274,9 +1274,6 @@ operator>>(std::istream & is, Triangulation & tr) { typedef Triangulation T; typedef typename T::Vertex_handle Vertex_handle; - typedef typename T::Vertex_iterator Vertex_iterator; - typedef typename T::Full_cell_handle Full_cell_handle; - typedef typename T::Full_cell_iterator Full_cell_iterator; // read current dimension and number of vertices size_t n; @@ -1330,8 +1327,6 @@ operator<<(std::ostream & os, const Triangulation & tr) typedef Triangulation T; typedef typename T::Vertex_const_handle Vertex_handle; typedef typename T::Vertex_const_iterator Vertex_iterator; - typedef typename T::Full_cell_const_handle Full_cell_handle; - typedef typename T::Full_cell_const_iterator Full_cell_iterator; // outputs dimensions and number of vertices size_t n = tr.number_of_vertices(); diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 9c4f3239a14..b1d3912f4a7 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -1458,9 +1458,6 @@ operator>>(std::istream & is, Triangulation_data_structure & tr) { typedef Triangulation_data_structure TDS; typedef typename TDS::Vertex_handle Vertex_handle; - typedef typename TDS::Vertex_iterator Vertex_iterator; - typedef typename TDS::Full_cell_handle Full_cell_handle; - typedef typename TDS::Full_cell_iterator Full_cell_iterator; // read current dimension and number of vertices size_t n; @@ -1512,8 +1509,6 @@ operator<<(std::ostream & os, const Triangulation_data_structure typedef Triangulation_data_structure TDS; typedef typename TDS::Vertex_const_handle Vertex_handle; typedef typename TDS::Vertex_const_iterator Vertex_iterator; - typedef typename TDS::Full_cell_const_handle Full_cell_handle; - typedef typename TDS::Full_cell_const_iterator Full_cell_iterator; // outputs dimension and number of vertices size_t n = tr.number_of_vertices(); diff --git a/Triangulation/test/Triangulation/delaunay.cpp b/Triangulation/test/Triangulation/delaunay.cpp index 13ab4f97cc8..e11de0f99be 100644 --- a/Triangulation/test/Triangulation/delaunay.cpp +++ b/Triangulation/test/Triangulation/delaunay.cpp @@ -19,14 +19,9 @@ void test(const int d, const string & type, const int N) // we must write 'typename' below, because we are in a template-function, // so the parser has no way to know that DC contains sub-types, before // instanciating the function. - typedef typename DC::Vertex Vertex; - typedef typename DC::Vertex_handle Vertex_handle; - typedef typename DC::Full_cell Full_cell; typedef typename DC::Full_cell_handle Full_cell_handle; - typedef typename DC::Facet Facet; typedef typename DC::Face Face; typedef typename DC::Point Point; - typedef typename DC::Geom_traits::RT RT; typedef typename DC::Finite_full_cell_const_iterator Finite_full_cell_const_iterator; typedef typename DC::Finite_vertex_iterator Finite_vertex_iterator; From 963ebc58bddfe7e58ecc0b54a07589ceb816b387 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Jun 2014 18:45:05 +0200 Subject: [PATCH 036/487] Test more dimensions --- Triangulation/test/Triangulation/regular.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Triangulation/test/Triangulation/regular.cpp b/Triangulation/test/Triangulation/regular.cpp index 8b6198dad8e..319cb9cec9e 100644 --- a/Triangulation/test/Triangulation/regular.cpp +++ b/Triangulation/test/Triangulation/regular.cpp @@ -124,11 +124,11 @@ int main(int argc, char **argv) int N = 10; if( argc > 1 ) N = atoi(argv[1]); - //go<5>(N); - //go<4>(N); - //go<3>(N); + go<5>(N); + go<4>(N); + go<3>(N); go<2>(N); - //go<1>(N); + go<1>(N); cerr << endl; return 0; From 7b9cfe41681941558052edf0aac29a37e21eab81 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Jun 2014 14:57:59 +0200 Subject: [PATCH 037/487] Fix tabulation (size = 2 spaces) --- Triangulation/include/CGAL/Triangulation.h | 1888 +++++++------- .../CGAL/Triangulation_data_structure.h | 2208 ++++++++--------- 2 files changed, 2048 insertions(+), 2048 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 3a0cda2631b..6ce98f370f1 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -48,18 +48,18 @@ public: typedef Point const& result_type; // For result_of Substitute_point_in_vertex_iterator( - Vertex_handle vh_where_point_should_be_substituted, - Point const *subtitute_point) + Vertex_handle vh_where_point_should_be_substituted, + Point const *subtitute_point) : vh_where_point_should_be_substituted_(vh_where_point_should_be_substituted) , subtitute_point_(subtitute_point) {} result_type operator()(Vertex_handle vh) const { - if (vh == vh_where_point_should_be_substituted_) - return *subtitute_point_; - else - return vh->point(); + if (vh == vh_where_point_should_be_substituted_) + return *subtitute_point_; + else + return vh->point(); } private: @@ -72,682 +72,682 @@ private: template < class TriangulationTraits, class TDS_ = Default > class Triangulation { - typedef typename TriangulationTraits::Dimension Maximal_dimension_; - typedef typename Default::Get, - Triangulation_full_cell > - >::type TDS; - typedef Triangulation Self; - + typedef typename TriangulationTraits::Dimension Maximal_dimension_; + typedef typename Default::Get, + Triangulation_full_cell > + >::type TDS; + typedef Triangulation Self; + protected: - typedef typename TriangulationTraits::Flat_orientation_d Flat_orientation_d; - typedef typename TriangulationTraits::Construct_flat_orientation_d Construct_flat_orientation_d; - typedef typename TriangulationTraits::In_flat_orientation_d In_flat_orientation_d; + typedef typename TriangulationTraits::Flat_orientation_d Flat_orientation_d; + typedef typename TriangulationTraits::Construct_flat_orientation_d Construct_flat_orientation_d; + typedef typename TriangulationTraits::In_flat_orientation_d In_flat_orientation_d; + + // Wrapper + struct Coaffine_orientation_d + { + boost::optional* fop; + Construct_flat_orientation_d cfo; + In_flat_orientation_d ifo; + + Coaffine_orientation_d( + boost::optional& x, + Construct_flat_orientation_d const&y, + In_flat_orientation_d const&z) + : fop(&x), cfo(y), ifo(z) {} - // Wrapper - struct Coaffine_orientation_d + template + CGAL::Orientation operator()(Iter a, Iter b) const { - boost::optional* fop; - Construct_flat_orientation_d cfo; - In_flat_orientation_d ifo; - - Coaffine_orientation_d( - boost::optional& x, - Construct_flat_orientation_d const&y, - In_flat_orientation_d const&z) - : fop(&x), cfo(y), ifo(z) {} - - template - CGAL::Orientation operator()(Iter a, Iter b) const - { - if (*fop) - return ifo(fop->get(),a,b); - *fop = cfo(a,b); - CGAL_assertion(ifo(fop->get(),a,b) == CGAL::POSITIVE); - return CGAL::POSITIVE; - } - }; - - void reset_flat_orientation() - { - if (current_dimension() == preset_flat_orientation_.first) - { - CGAL_assertion(preset_flat_orientation_.second != NULL); - flat_orientation_ = *preset_flat_orientation_.second; - } - else - flat_orientation_ = boost::none; + if (*fop) + return ifo(fop->get(),a,b); + *fop = cfo(a,b); + CGAL_assertion(ifo(fop->get(),a,b) == CGAL::POSITIVE); + return CGAL::POSITIVE; } + }; - typedef typename TriangulationTraits::Orientation_d - Orientation_d; + void reset_flat_orientation() + { + if (current_dimension() == preset_flat_orientation_.first) + { + CGAL_assertion(preset_flat_orientation_.second != NULL); + flat_orientation_ = *preset_flat_orientation_.second; + } + else + flat_orientation_ = boost::none; + } + + typedef typename TriangulationTraits::Orientation_d + Orientation_d; public: - typedef TriangulationTraits Geom_traits; - typedef TDS Triangulation_ds; + typedef TriangulationTraits Geom_traits; + typedef TDS Triangulation_ds; - typedef typename TDS::Vertex Vertex; - typedef typename TDS::Full_cell Full_cell; - typedef typename TDS::Facet Facet; - typedef typename TDS::Face Face; + typedef typename TDS::Vertex Vertex; + typedef typename TDS::Full_cell Full_cell; + typedef typename TDS::Facet Facet; + typedef typename TDS::Face Face; - typedef Maximal_dimension_ Maximal_dimension; - typedef typename Geom_traits::Point_d Point; + typedef Maximal_dimension_ Maximal_dimension; + typedef typename Geom_traits::Point_d Point; - typedef typename TDS::Vertex_handle Vertex_handle; - typedef typename TDS::Vertex_iterator Vertex_iterator; - typedef typename TDS::Vertex_const_handle Vertex_const_handle; - typedef typename TDS::Vertex_const_iterator Vertex_const_iterator; + typedef typename TDS::Vertex_handle Vertex_handle; + typedef typename TDS::Vertex_iterator Vertex_iterator; + typedef typename TDS::Vertex_const_handle Vertex_const_handle; + typedef typename TDS::Vertex_const_iterator Vertex_const_iterator; - typedef typename TDS::Full_cell_handle Full_cell_handle; - typedef typename TDS::Full_cell_iterator Full_cell_iterator; - typedef typename TDS::Full_cell_const_handle Full_cell_const_handle; - typedef typename TDS::Full_cell_const_iterator Full_cell_const_iterator; - - typedef typename TDS::Facet_iterator Facet_iterator; + typedef typename TDS::Full_cell_handle Full_cell_handle; + typedef typename TDS::Full_cell_iterator Full_cell_iterator; + typedef typename TDS::Full_cell_const_handle Full_cell_const_handle; + typedef typename TDS::Full_cell_const_iterator Full_cell_const_iterator; + + typedef typename TDS::Facet_iterator Facet_iterator; - typedef typename TDS::size_type size_type; - typedef typename TDS::difference_type difference_type; + typedef typename TDS::size_type size_type; + typedef typename TDS::difference_type difference_type; - /// The type of location a new point is found lying on - enum Locate_type - { - ON_VERTEX = 0 // simplex of dimension 0 - , IN_FACE = 1 // simplex of dimension in [ 1, |current_dimension()| - 2 ] - , IN_FACET = 2 // simplex of dimension |current_dimension()| - 1 - , IN_FULL_CELL = 3 /// simplex of dimension |current_dimension()| - , OUTSIDE_CONVEX_HULL = 4 - , OUTSIDE_AFFINE_HULL = 5 - }; + /// The type of location a new point is found lying on + enum Locate_type + { + ON_VERTEX = 0 // simplex of dimension 0 + , IN_FACE = 1 // simplex of dimension in [ 1, |current_dimension()| - 2 ] + , IN_FACET = 2 // simplex of dimension |current_dimension()| - 1 + , IN_FULL_CELL = 3 /// simplex of dimension |current_dimension()| + , OUTSIDE_CONVEX_HULL = 4 + , OUTSIDE_AFFINE_HULL = 5 + }; - // Finite elements iterators + // Finite elements iterators - class Finiteness_predicate; + class Finiteness_predicate; - typedef boost::filter_iterator - Finite_vertex_iterator; - typedef boost::filter_iterator - Finite_vertex_const_iterator; - typedef boost::filter_iterator - Finite_full_cell_iterator; - typedef boost::filter_iterator - Finite_full_cell_const_iterator; - typedef boost::filter_iterator - Finite_facet_iterator; + typedef boost::filter_iterator + Finite_vertex_iterator; + typedef boost::filter_iterator + Finite_vertex_const_iterator; + typedef boost::filter_iterator + Finite_full_cell_iterator; + typedef boost::filter_iterator + Finite_full_cell_const_iterator; + typedef boost::filter_iterator + Finite_facet_iterator; protected: // DATA MEMBERS - Triangulation_ds tds_; - const Geom_traits kernel_; - Vertex_handle infinity_; - mutable std::vector orientations_; - mutable boost::optional flat_orientation_; - // The user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension - // (= preset_flat_orientation_.first) - // preset_flat_orientation_.first = numeric_limits::max() otherwise) - std::pair preset_flat_orientation_; - // for stochastic walk in the locate() function: - mutable Random rng_; + Triangulation_ds tds_; + const Geom_traits kernel_; + Vertex_handle infinity_; + mutable std::vector orientations_; + mutable boost::optional flat_orientation_; + // The user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // preset_flat_orientation_.first = numeric_limits::max() otherwise) + std::pair preset_flat_orientation_; + // for stochastic walk in the locate() function: + mutable Random rng_; #ifdef CGAL_TRIANGULATION_STATISTICS - mutable unsigned long walk_size_; + mutable unsigned long walk_size_; #endif protected: // HELPER FUNCTIONS - typedef CGAL::Iterator_project< - typename Full_cell::Vertex_handle_const_iterator, - internal::Triangulation::Point_from_vertex_handle - > Point_const_iterator; + typedef CGAL::Iterator_project< + typename Full_cell::Vertex_handle_const_iterator, + internal::Triangulation::Point_from_vertex_handle + > Point_const_iterator; - Point_const_iterator points_begin(Full_cell_const_handle c) const - { return Point_const_iterator(c->vertices_begin()); } - Point_const_iterator points_end(Full_cell_const_handle c) const - { return Point_const_iterator(c->vertices_end()); } - Point_const_iterator points_begin(Full_cell_handle c) const - { return Point_const_iterator(c->vertices_begin()); } - Point_const_iterator points_end(Full_cell_handle c) const - { return Point_const_iterator(c->vertices_end()); } + Point_const_iterator points_begin(Full_cell_const_handle c) const + { return Point_const_iterator(c->vertices_begin()); } + Point_const_iterator points_end(Full_cell_const_handle c) const + { return Point_const_iterator(c->vertices_end()); } + Point_const_iterator points_begin(Full_cell_handle c) const + { return Point_const_iterator(c->vertices_begin()); } + Point_const_iterator points_end(Full_cell_handle c) const + { return Point_const_iterator(c->vertices_end()); } public: - // FACETS OPERATIONS + // FACETS OPERATIONS - Full_cell_handle full_cell(const Facet & f) const - { - return tds().full_cell(f); - } + Full_cell_handle full_cell(const Facet & f) const + { + return tds().full_cell(f); + } - int index_of_covertex(const Facet & f) const - { - return tds().index_of_covertex(f); - } - + int index_of_covertex(const Facet & f) const + { + return tds().index_of_covertex(f); + } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UTILITIES - // A co-dimension 2 sub-simplex. called a Rotor because we can rotate - // the two "covertices" around the sub-simplex. Useful for traversing the - // boundary of a hole. NOT DOCUMENTED - typedef cpp11::tuple Rotor; - Full_cell_handle full_cell(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<0>(r); - } - int index_of_covertex(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<1>(r); - } - int index_of_second_covertex(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<2>(r); - } - Rotor rotate_rotor(Rotor & r) // NOT DOCUMENTED... - { - int opposite = full_cell(r)->mirror_index(index_of_covertex(r)); - Full_cell_handle s = full_cell(r)->neighbor(index_of_covertex(r)); - int new_second = s->index(full_cell(r)->vertex(index_of_second_covertex(r))); - return Rotor(s, new_second, opposite); - } + // A co-dimension 2 sub-simplex. called a Rotor because we can rotate + // the two "covertices" around the sub-simplex. Useful for traversing the + // boundary of a hole. NOT DOCUMENTED + typedef cpp11::tuple Rotor; + Full_cell_handle full_cell(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<0>(r); + } + int index_of_covertex(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<1>(r); + } + int index_of_second_covertex(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<2>(r); + } + Rotor rotate_rotor(Rotor & r) // NOT DOCUMENTED... + { + int opposite = full_cell(r)->mirror_index(index_of_covertex(r)); + Full_cell_handle s = full_cell(r)->neighbor(index_of_covertex(r)); + int new_second = s->index(full_cell(r)->vertex(index_of_second_covertex(r))); + return Rotor(s, new_second, opposite); + } - // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS + // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS - Triangulation(int dim, const Geom_traits k = Geom_traits()) - : tds_(dim) - , kernel_(k) - , infinity_() - , preset_flat_orientation_(std::numeric_limits::max(), NULL) - , rng_((long)0) + Triangulation(int dim, const Geom_traits k = Geom_traits()) + : tds_(dim) + , kernel_(k) + , infinity_() + , preset_flat_orientation_(std::numeric_limits::max(), NULL) + , rng_((long)0) #ifdef CGAL_TRIANGULATION_STATISTICS - ,walk_size_(0) + ,walk_size_(0) #endif - { - clear(); - } + { + clear(); + } - // With this constructor, - // the user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension - // (= preset_flat_orientation_.first) - // It it used for by dark triangulations created by DT::remove - Triangulation( - int dim, - const std::pair &preset_flat_orientation, - const Geom_traits k = Geom_traits()) - : tds_(dim) - , kernel_(k) - , infinity_() - , preset_flat_orientation_(preset_flat_orientation) - , rng_((long)0) + // With this constructor, + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // It it used for by dark triangulations created by DT::remove + Triangulation( + int dim, + const std::pair &preset_flat_orientation, + const Geom_traits k = Geom_traits()) + : tds_(dim) + , kernel_(k) + , infinity_() + , preset_flat_orientation_(preset_flat_orientation) + , rng_((long)0) #ifdef CGAL_TRIANGULATION_STATISTICS - ,walk_size_(0) + ,walk_size_(0) #endif - { - clear(); - } - - Triangulation(const Triangulation & t2) - : tds_(t2.tds_) - , kernel_(t2.kernel_) - , infinity_() - , preset_flat_orientation_(std::numeric_limits::max(), NULL) - , rng_(t2.rng_) + { + clear(); + } + + Triangulation(const Triangulation & t2) + : tds_(t2.tds_) + , kernel_(t2.kernel_) + , infinity_() + , preset_flat_orientation_(std::numeric_limits::max(), NULL) + , rng_(t2.rng_) #ifdef CGAL_TRIANGULATION_STATISTICS - ,walk_size_(t2.walk_size_) + ,walk_size_(t2.walk_size_) #endif + { + // We find the vertex at infinity by scanning the vertices of both + // triangulations. This works because Compact_container garantees that + // the vertices in the copy (*this) are stored in the same order as in + // the original triangulation (t2) + infinity_ = vertices_begin(); + Vertex_const_iterator inf2 = t2.vertices_begin(); + while( inf2 != t2.infinite_vertex() ) { - // We find the vertex at infinity by scanning the vertices of both - // triangulations. This works because Compact_container garantees that - // the vertices in the copy (*this) are stored in the same order as in - // the original triangulation (t2) - infinity_ = vertices_begin(); - Vertex_const_iterator inf2 = t2.vertices_begin(); - while( inf2 != t2.infinite_vertex() ) - { - ++infinity_; - ++inf2; - } - // A full_cell has at most 1 + maximal_dimension() facets: - orientations_.resize(1 + maximal_dimension()); - // Our coaffine orientation predicates HAS state member variables - reset_flat_orientation(); + ++infinity_; + ++inf2; } + // A full_cell has at most 1 + maximal_dimension() facets: + orientations_.resize(1 + maximal_dimension()); + // Our coaffine orientation predicates HAS state member variables + reset_flat_orientation(); + } - ~Triangulation() {} + ~Triangulation() {} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS FUNCTIONS + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS FUNCTIONS - /* These three function are no longer needed since we do not use them anymore - in the Delaunay_triangulation::remove. *But*, they may reappear in the future - if we manage to passe the information that flags/TDS_data is available or not - for marking simplices in Delaunay_triangulation::remove. This would be useful - to make it a little faster, instead of binary searching if a simplex is marked - or not... - // NOT DOCUMENTED -- - bool get_visited(Full_cell_handle s) const - { - return tds().get_visited(s); - } - // NOT DOCUMENTED -- - bool get_visited(Full_cell_const_handle s) const - { - return tds().get_visited(s); - } + /* These three function are no longer needed since we do not use them anymore + in the Delaunay_triangulation::remove. *But*, they may reappear in the future + if we manage to passe the information that flags/TDS_data is available or not + for marking simplices in Delaunay_triangulation::remove. This would be useful + to make it a little faster, instead of binary searching if a simplex is marked + or not... + // NOT DOCUMENTED -- + bool get_visited(Full_cell_handle s) const + { + return tds().get_visited(s); + } + // NOT DOCUMENTED -- + bool get_visited(Full_cell_const_handle s) const + { + return tds().get_visited(s); + } - // NOT DOCUMENTED -- - void set_visited(Full_cell_handle s, bool b) const - { - tds().set_visited(s, b); - } */ + // NOT DOCUMENTED -- + void set_visited(Full_cell_handle s, bool b) const + { + tds().set_visited(s, b); + } */ - Coaffine_orientation_d coaffine_orientation_predicate() const - { - return Coaffine_orientation_d ( - flat_orientation_, - geom_traits().construct_flat_orientation_d_object(), - geom_traits().in_flat_orientation_d_object() - ); - } + Coaffine_orientation_d coaffine_orientation_predicate() const + { + return Coaffine_orientation_d ( + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), + geom_traits().in_flat_orientation_d_object() + ); + } - const Triangulation_ds & tds() const - { - return tds_; - } + const Triangulation_ds & tds() const + { + return tds_; + } - Triangulation_ds & tds() - { - return tds_; - } + Triangulation_ds & tds() + { + return tds_; + } - const Geom_traits & geom_traits() const - { - return kernel_; - } + const Geom_traits & geom_traits() const + { + return kernel_; + } - int maximal_dimension() const { return tds().maximal_dimension(); } - int current_dimension() const { return tds().current_dimension(); } + int maximal_dimension() const { return tds().maximal_dimension(); } + int current_dimension() const { return tds().current_dimension(); } - bool empty() const - { - return current_dimension() == -1; - } + bool empty() const + { + return current_dimension() == -1; + } - size_type number_of_vertices() const - { - return tds().number_of_vertices() - 1; - } + size_type number_of_vertices() const + { + return tds().number_of_vertices() - 1; + } - size_type number_of_full_cells() const - { - return tds().number_of_full_cells(); - } + size_type number_of_full_cells() const + { + return tds().number_of_full_cells(); + } - Vertex_handle infinite_vertex() const - { - return infinity_; - } + Vertex_handle infinite_vertex() const + { + return infinity_; + } - Full_cell_handle infinite_full_cell() const - { - CGAL_assertion(infinite_vertex()->full_cell()->has_vertex(infinite_vertex())); - return infinite_vertex()->full_cell(); - } + Full_cell_handle infinite_full_cell() const + { + CGAL_assertion(infinite_vertex()->full_cell()->has_vertex(infinite_vertex())); + return infinite_vertex()->full_cell(); + } // - - - - - - - - - - - - - - - - - - - - - - - - - NON CONSTANT-TIME ACCESS FUNCTIONS - size_type number_of_finite_full_cells() const + size_type number_of_finite_full_cells() const + { + Full_cell_const_iterator s = full_cells_begin(); + size_type result = number_of_full_cells(); + for( ; s != full_cells_end(); ++s ) { - Full_cell_const_iterator s = full_cells_begin(); - size_type result = number_of_full_cells(); - for( ; s != full_cells_end(); ++s ) - { - if( is_infinite(s) ) - --result; - } - return result; + if( is_infinite(s) ) + --result; } + return result; + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRAVERSAL - Vertex_iterator vertices_begin() { return tds().vertices_begin(); } - Vertex_iterator vertices_end() { return tds().vertices_end(); } + Vertex_iterator vertices_begin() { return tds().vertices_begin(); } + Vertex_iterator vertices_end() { return tds().vertices_end(); } - Vertex_const_iterator vertices_begin() const { return tds().vertices_begin(); } - Vertex_const_iterator vertices_end() const { return tds().vertices_end(); } + Vertex_const_iterator vertices_begin() const { return tds().vertices_begin(); } + Vertex_const_iterator vertices_end() const { return tds().vertices_end(); } - Finite_vertex_iterator finite_vertices_begin() - { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } - Finite_vertex_iterator finite_vertices_end() - { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } - Finite_vertex_const_iterator finite_vertices_begin() const - { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } - Finite_vertex_const_iterator finite_vertices_end() const - { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } + Finite_vertex_iterator finite_vertices_begin() + { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } + Finite_vertex_iterator finite_vertices_end() + { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } + Finite_vertex_const_iterator finite_vertices_begin() const + { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } + Finite_vertex_const_iterator finite_vertices_end() const + { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } - Full_cell_iterator full_cells_begin() { return tds().full_cells_begin(); } - Full_cell_iterator full_cells_end() { return tds().full_cells_end(); } + Full_cell_iterator full_cells_begin() { return tds().full_cells_begin(); } + Full_cell_iterator full_cells_end() { return tds().full_cells_end(); } - Full_cell_const_iterator full_cells_begin() const { return tds().full_cells_begin(); } - Full_cell_const_iterator full_cells_end() const { return tds().full_cells_end(); } + Full_cell_const_iterator full_cells_begin() const { return tds().full_cells_begin(); } + Full_cell_const_iterator full_cells_end() const { return tds().full_cells_end(); } - Finite_full_cell_iterator finite_full_cells_begin() - { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } - Finite_full_cell_iterator finite_full_cells_end() - { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } - Finite_full_cell_const_iterator finite_full_cells_begin() const - { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } - Finite_full_cell_const_iterator finite_full_cells_end() const - { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } + Finite_full_cell_iterator finite_full_cells_begin() + { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } + Finite_full_cell_iterator finite_full_cells_end() + { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } + Finite_full_cell_const_iterator finite_full_cells_begin() const + { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } + Finite_full_cell_const_iterator finite_full_cells_end() const + { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } - Facet_iterator facets_begin() { return tds().facets_begin(); } - Facet_iterator facets_end() { return tds().facets_end(); } - Facet_iterator finite_facets_begin() - { return Finite_facet_iterator(Finiteness_predicate(*this), facets_begin(), facets_end()); } - Facet_iterator finite_facets_end() - { return Finite_facet_iterator(Finiteness_predicate(*this), facets_end(), facets_end()); } + Facet_iterator facets_begin() { return tds().facets_begin(); } + Facet_iterator facets_end() { return tds().facets_end(); } + Facet_iterator finite_facets_begin() + { return Finite_facet_iterator(Finiteness_predicate(*this), facets_begin(), facets_end()); } + Facet_iterator finite_facets_end() + { return Finite_facet_iterator(Finiteness_predicate(*this), facets_end(), facets_end()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SOME PREDICATE FUNCTORS - class Finiteness_predicate + class Finiteness_predicate + { + const Self & t_; + public: + Finiteness_predicate(const Self & t) : t_(t) {} + template < class T > + bool operator()(const T & t) const { - const Self & t_; - public: - Finiteness_predicate(const Self & t) : t_(t) {} - template < class T > - bool operator()(const T & t) const - { - return ! t_.is_infinite(t); - } - }; + return ! t_.is_infinite(t); + } + }; - class Point_equality_predicate - { - const Point & o_; - public: - Point_equality_predicate(const Point & o) : o_(o) {} - bool operator()(const Point & o) const { return (o == o_ );} - }; + class Point_equality_predicate + { + const Point & o_; + public: + Point_equality_predicate(const Point & o) : o_(o) {} + bool operator()(const Point & o) const { return (o == o_ );} + }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SIMPLE QUERIES /* - bool is_vertex(const Point & p, Vertex_handle & v, Full_cell_handle hint = Full_cell_handle()) const + bool is_vertex(const Point & p, Vertex_handle & v, Full_cell_handle hint = Full_cell_handle()) const + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, hint); + if( ON_VERTEX == lt ) { - Locate_type lt; - Face f(maximal_dimension()); - Facet ft; - Full_cell_handle s = locate(p, lt, f, ft, hint); - if( ON_VERTEX == lt ) - { - v = s->vertex(f.index(0)); - return true; - } - return false; + v = s->vertex(f.index(0)); + return true; } + return false; + } - bool is_vertex(Vertex_const_handle v) const - { - return tds().is_vertex(v); - } + bool is_vertex(Vertex_const_handle v) const + { + return tds().is_vertex(v); + } - bool is_full_cell(Full_cell_const_handle s) const - { - return tds().is_full_cell(s); - } + bool is_full_cell(Full_cell_const_handle s) const + { + return tds().is_full_cell(s); + } */ - bool is_infinite(Vertex_const_handle v) const - { - CGAL_precondition(Vertex_const_handle() != v); - return (infinite_vertex() == v); - } + bool is_infinite(Vertex_const_handle v) const + { + CGAL_precondition(Vertex_const_handle() != v); + return (infinite_vertex() == v); + } - bool is_infinite(const Vertex & v) const /* internal use, not documented */ - { - return (&(*infinite_vertex()) == &v); - } + bool is_infinite(const Vertex & v) const /* internal use, not documented */ + { + return (&(*infinite_vertex()) == &v); + } - bool is_infinite(Full_cell_const_handle s) const - { - CGAL_precondition(Full_cell_const_handle() != s); - return is_infinite(*s); - } - bool is_infinite(const Full_cell & s) const /* internal use, not documented */ - { - for(int i = 0; i <= current_dimension(); ++i) - if( is_infinite(s.vertex(i)) ) - return true; - return false; - } - bool is_infinite(const Facet & ft) const - { - Full_cell_const_handle s = full_cell(ft); - CGAL_precondition(s != Full_cell_handle()); - if( is_infinite(s) ) - return (s->vertex(index_of_covertex(ft)) != infinite_vertex()); - return false; - } + bool is_infinite(Full_cell_const_handle s) const + { + CGAL_precondition(Full_cell_const_handle() != s); + return is_infinite(*s); + } + bool is_infinite(const Full_cell & s) const /* internal use, not documented */ + { + for(int i = 0; i <= current_dimension(); ++i) + if( is_infinite(s.vertex(i)) ) + return true; + return false; + } + bool is_infinite(const Facet & ft) const + { + Full_cell_const_handle s = full_cell(ft); + CGAL_precondition(s != Full_cell_handle()); + if( is_infinite(s) ) + return (s->vertex(index_of_covertex(ft)) != infinite_vertex()); + return false; + } - bool is_infinite(const Face & f) const + bool is_infinite(const Face & f) const + { + Full_cell_const_handle s = f.full_cell(); + CGAL_precondition(s != Full_cell_handle()); + if( is_infinite(s) ) { - Full_cell_const_handle s = f.full_cell(); - CGAL_precondition(s != Full_cell_handle()); - if( is_infinite(s) ) - { - Vertex_handle v; - for( int i(0); i<= f.face_dimension(); ++i) - if ( is_infinite( f.vertex(i) )) return true; - } - return false; + Vertex_handle v; + for( int i(0); i<= f.face_dimension(); ++i) + if ( is_infinite( f.vertex(i) )) return true; } + return false; + } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ELEMENT GATHERING + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ELEMENT GATHERING - - template< typename OutputIterator > - OutputIterator incident_full_cells(const Face & f, OutputIterator out) const - { - return tds().incident_full_cells(f, out); - } - template< typename OutputIterator > - OutputIterator incident_full_cells(Vertex_const_handle v, OutputIterator out) const - { - return tds().incident_full_cells(v, out); - } - template< typename OutputIterator > - OutputIterator star(const Face & f, OutputIterator out) const - { - return tds().star(f, out); - } + + template< typename OutputIterator > + OutputIterator incident_full_cells(const Face & f, OutputIterator out) const + { + return tds().incident_full_cells(f, out); + } + template< typename OutputIterator > + OutputIterator incident_full_cells(Vertex_const_handle v, OutputIterator out) const + { + return tds().incident_full_cells(v, out); + } + template< typename OutputIterator > + OutputIterator star(const Face & f, OutputIterator out) const + { + return tds().star(f, out); + } - template< typename OutputIterator > - OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) + template< typename OutputIterator > + OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) + { + return tds().incident_faces(v, d, out); + } + /* + template< typename OutputIterator, class Comparator > + OutputIterator incident_upper_faces( Vertex_const_handle v, int d, + OutputIterator out, Comparator cmp = Comparator()) + { + return tds().incident_upper_faces(v, d, out, cmp); + } + template< typename OutputIterator > + OutputIterator incident_upper_faces( Vertex_const_handle v, int d, + OutputIterator out) + { // FIXME: uncomment this function, since it uses a comparator specific to + // *geometric* triangulation (taking infinite vertex into account) + internal::Triangulation::Compare_vertices_for_upper_face cmp(*this); + return tds().incident_upper_faces(v, d, out, cmp); + } + */ + Orientation orientation(Full_cell_const_handle s, bool in_is_valid = false) const + { + if( ! in_is_valid ) + CGAL_assertion( ! is_infinite(s) ); + if( 0 == current_dimension() ) + return POSITIVE; + if( current_dimension() == maximal_dimension() ) { - return tds().incident_faces(v, d, out); + Orientation_d ori = geom_traits().orientation_d_object(); + return ori(points_begin(s), points_begin(s) + 1 + current_dimension()); } - /* - template< typename OutputIterator, class Comparator > - OutputIterator incident_upper_faces( Vertex_const_handle v, int d, - OutputIterator out, Comparator cmp = Comparator()) + else { - return tds().incident_upper_faces(v, d, out, cmp); - } - template< typename OutputIterator > - OutputIterator incident_upper_faces( Vertex_const_handle v, int d, - OutputIterator out) - { // FIXME: uncomment this function, since it uses a comparator specific to - // *geometric* triangulation (taking infinite vertex into account) - internal::Triangulation::Compare_vertices_for_upper_face cmp(*this); - return tds().incident_upper_faces(v, d, out, cmp); - } - */ - Orientation orientation(Full_cell_const_handle s, bool in_is_valid = false) const - { - if( ! in_is_valid ) - CGAL_assertion( ! is_infinite(s) ); - if( 0 == current_dimension() ) - return POSITIVE; - if( current_dimension() == maximal_dimension() ) - { - Orientation_d ori = geom_traits().orientation_d_object(); - return ori(points_begin(s), points_begin(s) + 1 + current_dimension()); - } - else - { - return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); - } + return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); } + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UPDATE OPERATIONS - void clear() - { - tds_.clear(); - infinity_ = tds().insert_increase_dimension(); - // A full_cell has at most 1 + maximal_dimension() facets: - orientations_.resize(1 + maximal_dimension()); - // Our coaffine orientation predicates HAS state member variables - reset_flat_orientation(); + void clear() + { + tds_.clear(); + infinity_ = tds().insert_increase_dimension(); + // A full_cell has at most 1 + maximal_dimension() facets: + orientations_.resize(1 + maximal_dimension()); + // Our coaffine orientation predicates HAS state member variables + reset_flat_orientation(); #ifdef CGAL_TRIANGULATION_STATISTICS - walk_size_ = 0; + walk_size_ = 0; #endif - } + } - void set_current_dimension(int d) - { - tds().set_current_dimension(d); - } + void set_current_dimension(int d) + { + tds().set_current_dimension(d); + } - Full_cell_handle new_full_cell() - { - return tds().new_full_cell(); - } + Full_cell_handle new_full_cell() + { + return tds().new_full_cell(); + } - Vertex_handle new_vertex(const Point & p) - { - return tds().new_vertex(p); - } + Vertex_handle new_vertex(const Point & p) + { + return tds().new_vertex(p); + } - void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) - { - tds().set_neighbors(s, i, s1, j); - } + void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) + { + tds().set_neighbors(s, i, s1, j); + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY - bool is_valid(bool = false, int = 0) const; - bool are_incident_full_cells_valid(Vertex_const_handle, bool = false, int = 0) const; + bool is_valid(bool = false, int = 0) const; + bool are_incident_full_cells_valid(Vertex_const_handle, bool = false, int = 0) const; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POINT LOCATION protected: - template< typename OrientationPredicate > - Full_cell_handle do_locate( const Point &, Locate_type &, Face &, Facet &, - Full_cell_handle start, - const OrientationPredicate & o) const; + template< typename OrientationPredicate > + Full_cell_handle do_locate( const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle start, + const OrientationPredicate & o) const; public: - Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, - Full_cell_handle start = Full_cell_handle()) const; - Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, - Vertex_handle) const; - Full_cell_handle locate(const Point & p, Full_cell_handle s = Full_cell_handle()) const; - Full_cell_handle locate(const Point & p, Vertex_handle v) const; + Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle start = Full_cell_handle()) const; + Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, + Vertex_handle) const; + Full_cell_handle locate(const Point & p, Full_cell_handle s = Full_cell_handle()) const; + Full_cell_handle locate(const Point & p, Vertex_handle v) const; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS - Vertex_handle contract_face(const Point &, const Face &); + Vertex_handle contract_face(const Point &, const Face &); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POINT INSERTION - template< typename ForwardIterator > - size_type insert(ForwardIterator start, ForwardIterator end) + template< typename ForwardIterator > + size_type insert(ForwardIterator start, ForwardIterator end) + { + size_type n = number_of_vertices(); + std::vector points(start, end); + spatial_sort(points.begin(), points.end(), geom_traits()); + Full_cell_handle hint = Full_cell_handle(); + typename std::vector::const_iterator s = points.begin(); + while( s != points.end() ) { - size_type n = number_of_vertices(); - std::vector points(start, end); - spatial_sort(points.begin(), points.end(), geom_traits()); - Full_cell_handle hint = Full_cell_handle(); - typename std::vector::const_iterator s = points.begin(); - while( s != points.end() ) - { - hint = insert(*s++, hint)->full_cell(); - } - return number_of_vertices() - n; + hint = insert(*s++, hint)->full_cell(); } - Vertex_handle insert(const Point &, const Locate_type, const Face &, const Facet &, const Full_cell_handle); - Vertex_handle insert(const Point &, Full_cell_handle start = Full_cell_handle()); - Vertex_handle insert(const Point &, Vertex_handle); - template< typename ForwardIterator > - Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft) - { - Emptyset_iterator out; - return insert_in_hole(p, start, end, ft, out); - } - template< typename ForwardIterator, typename OutputIterator > - Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft, - OutputIterator out) - { - Vertex_handle v = tds().insert_in_hole(start, end, ft, out); - v->set_point(p); - return v; - } - Vertex_handle insert_in_face(const Point &, const Face &); - Vertex_handle insert_in_facet(const Point &, const Facet &); - Vertex_handle insert_in_full_cell(const Point &, Full_cell_handle); - Vertex_handle insert_outside_convex_hull_1(const Point &, Full_cell_handle); - Vertex_handle insert_outside_convex_hull(const Point &, Full_cell_handle); - Vertex_handle insert_outside_affine_hull(const Point &); + return number_of_vertices() - n; + } + Vertex_handle insert(const Point &, const Locate_type, const Face &, const Facet &, const Full_cell_handle); + Vertex_handle insert(const Point &, Full_cell_handle start = Full_cell_handle()); + Vertex_handle insert(const Point &, Vertex_handle); + template< typename ForwardIterator > + Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft) + { + Emptyset_iterator out; + return insert_in_hole(p, start, end, ft, out); + } + template< typename ForwardIterator, typename OutputIterator > + Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft, + OutputIterator out) + { + Vertex_handle v = tds().insert_in_hole(start, end, ft, out); + v->set_point(p); + return v; + } + Vertex_handle insert_in_face(const Point &, const Face &); + Vertex_handle insert_in_facet(const Point &, const Facet &); + Vertex_handle insert_in_full_cell(const Point &, Full_cell_handle); + Vertex_handle insert_outside_convex_hull_1(const Point &, Full_cell_handle); + Vertex_handle insert_outside_convex_hull(const Point &, Full_cell_handle); + Vertex_handle insert_outside_affine_hull(const Point &); // - - - - - - - - - - - - - - - - - - - - - - - - - - - FACET-TRAVERSAL PREDICATES - template< typename OrientationPredicate > - class Outside_convex_hull_traversal_predicate + template< typename OrientationPredicate > + class Outside_convex_hull_traversal_predicate + { + Triangulation & t_; + const Point & p_; + OrientationPredicate const& ori_; + int cur_dim_; + public: + Outside_convex_hull_traversal_predicate(Triangulation & t, const Point & p, + OrientationPredicate const& ori) + : t_(t), p_(p), ori_(ori), cur_dim_(t.current_dimension()) {} + // FUTURE change parameter to const reference + bool operator()(Facet f) const { - Triangulation & t_; - const Point & p_; - OrientationPredicate const& ori_; - int cur_dim_; - public: - Outside_convex_hull_traversal_predicate(Triangulation & t, const Point & p, - OrientationPredicate const& ori) - : t_(t), p_(p), ori_(ori), cur_dim_(t.current_dimension()) {} - // FUTURE change parameter to const reference - bool operator()(Facet f) const - { - Full_cell_handle s = t_.full_cell(f); - const int i = t_.index_of_covertex(f); - Full_cell_handle n = s->neighbor(i); - if( ! t_.is_infinite(n) ) - return false; - // FIXME: infinite vertex is NOT at index 0 a priori. - n->vertex(0)->set_point(p_); - bool ok = (POSITIVE == ori_(t_.points_begin(n), t_.points_begin(n) + cur_dim_ + 1)); - return ok; - } - }; + Full_cell_handle s = t_.full_cell(f); + const int i = t_.index_of_covertex(f); + Full_cell_handle n = s->neighbor(i); + if( ! t_.is_infinite(n) ) + return false; + // FIXME: infinite vertex is NOT at index 0 a priori. + n->vertex(0)->set_point(p_); + bool ok = (POSITIVE == ori_(t_.points_begin(n), t_.points_begin(n) + cur_dim_ + 1)); + return ok; + } + }; - // make sure all full_cells have positive orientation - void reorient_full_cells(); + // make sure all full_cells have positive orientation + void reorient_full_cells(); protected: // This is used in the |remove(v)| member function to manage sets of Full_cell_handles template< typename FCH > struct Full_cell_set : public std::vector { - typedef std::vector Base_set; - using Base_set::begin; - using Base_set::end; - void make_searchable() - { // sort the full cell handles - std::sort(begin(), end()); - } - bool contains(const FCH & fch) const - { - return std::binary_search(begin(), end(), fch); - } - bool contains_1st_and_not_2nd(const FCH & fst, const FCH & snd) const - { - return ( ! contains(snd) ) && ( contains(fst) ); - } + typedef std::vector Base_set; + using Base_set::begin; + using Base_set::end; + void make_searchable() + { // sort the full cell handles + std::sort(begin(), end()); + } + bool contains(const FCH & fch) const + { + return std::binary_search(begin(), end(), fch); + } + bool contains_1st_and_not_2nd(const FCH & fst, const FCH & snd) const + { + return ( ! contains(snd) ) && ( contains(fst) ); + } }; }; // Triangulation<...> @@ -761,20 +761,20 @@ void Triangulation ::reorient_full_cells() { - if( current_dimension() < 1 ) - return; - Full_cell_iterator sit = full_cells_begin(); - Full_cell_iterator send = full_cells_end(); - while( sit != send ) + if( current_dimension() < 1 ) + return; + Full_cell_iterator sit = full_cells_begin(); + Full_cell_iterator send = full_cells_end(); + while( sit != send ) + { + if( is_infinite(sit) && (1 == current_dimension()) ) { - if( is_infinite(sit) && (1 == current_dimension()) ) - { - ++sit; - continue; - } - sit->swap_vertices(current_dimension() - 1, current_dimension()); - ++sit; + ++sit; + continue; } + sit->swap_vertices(current_dimension() - 1, current_dimension()); + ++sit; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -785,11 +785,11 @@ typename Triangulation::Vertex_handle Triangulation ::contract_face(const Point & p, const Face & f) { - CGAL_precondition( ! is_infinite(f) ); - Vertex_handle v = tds().contract_face(f); - v->set_point(p); - CGAL_expensive_postcondition_msg(are_incident_full_cells_valid(v), "new point is not where it should be"); - return v; + CGAL_precondition( ! is_infinite(f) ); + Vertex_handle v = tds().contract_face(f); + v->set_point(p); + CGAL_expensive_postcondition_msg(are_incident_full_cells_valid(v), "new point is not where it should be"); + return v; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -800,32 +800,32 @@ typename Triangulation::Vertex_handle Triangulation ::insert(const Point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) { - switch( lt ) + switch( lt ) + { + case IN_FULL_CELL: + return insert_in_full_cell(p, s); + break; + case OUTSIDE_CONVEX_HULL: + return insert_outside_convex_hull(p, s); + break; + case OUTSIDE_AFFINE_HULL: + return insert_outside_affine_hull(p); + break; + case IN_FACET: { - case IN_FULL_CELL: - return insert_in_full_cell(p, s); - break; - case OUTSIDE_CONVEX_HULL: - return insert_outside_convex_hull(p, s); - break; - case OUTSIDE_AFFINE_HULL: - return insert_outside_affine_hull(p); - break; - case IN_FACET: - { - return insert_in_facet(p, ft); - break; - } - case IN_FACE: - return insert_in_face(p, f); - break; - case ON_VERTEX: - s->vertex(f.index(0))->set_point(p); - return s->vertex(f.index(0)); - break; + return insert_in_facet(p, ft); + break; } - CGAL_assertion(false); - return Vertex_handle(); + case IN_FACE: + return insert_in_face(p, f); + break; + case ON_VERTEX: + s->vertex(f.index(0))->set_point(p); + return s->vertex(f.index(0)); + break; + } + CGAL_assertion(false); + return Vertex_handle(); } template < class TT, class TDS > @@ -833,11 +833,11 @@ typename Triangulation::Vertex_handle Triangulation ::insert(const Point & p, Full_cell_handle start) { - Locate_type lt; - Face f(maximal_dimension()); - Facet ft; - Full_cell_handle s = locate(p, lt, f, ft, start); - return insert(p, lt, f, ft, s); + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, start); + return insert(p, lt, f, ft, s); } template < class TT, class TDS > @@ -845,9 +845,9 @@ typename Triangulation::Vertex_handle Triangulation ::insert(const Point & p, Vertex_handle v) { - if( Vertex_handle() == v ) - v = infinite_vertex(); - return insert(p, v->full_cell()); + if( Vertex_handle() == v ) + v = infinite_vertex(); + return insert(p, v->full_cell()); } template < class TT, class TDS > @@ -855,10 +855,10 @@ typename Triangulation::Vertex_handle Triangulation ::insert_in_face(const Point & p, const Face & f) { - CGAL_precondition( ! is_infinite(f) ); - Vertex_handle v = tds().insert_in_face(f); - v->set_point(p); - return v; + CGAL_precondition( ! is_infinite(f) ); + Vertex_handle v = tds().insert_in_face(f); + v->set_point(p); + return v; } template < class TT, class TDS > @@ -866,10 +866,10 @@ typename Triangulation::Vertex_handle Triangulation ::insert_in_facet(const Point & p, const Facet & ft) { - CGAL_precondition( ! is_infinite(ft) ); - Vertex_handle v = tds().insert_in_facet(ft); - v->set_point(p); - return v; + CGAL_precondition( ! is_infinite(ft) ); + Vertex_handle v = tds().insert_in_facet(ft); + v->set_point(p); + return v; } template < class TT, class TDS > @@ -877,10 +877,10 @@ typename Triangulation::Vertex_handle Triangulation ::insert_in_full_cell(const Point & p, Full_cell_handle s) { - CGAL_precondition( ! is_infinite(s) ); - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - return v; + CGAL_precondition( ! is_infinite(s) ); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + return v; } // NOT DOCUMENTED... @@ -889,20 +889,20 @@ typename Triangulation::Vertex_handle Triangulation ::insert_outside_convex_hull_1(const Point & p, Full_cell_handle s) { - // This is a special case for dimension 1, because in that case, the right - // infinite full_cell is not correctly oriented... (sice its first vertex is the - // infinite one... - CGAL_precondition( is_infinite(s) ); - CGAL_precondition( 1 == current_dimension() ); - // FIXME: infinite vertex is NOT at index 0 a priori. But I'm not sure it's a problem here. - bool swap = (0 == s->neighbor(0)->index(s)); - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - if( swap ) - { - s->swap_vertices(0, 1); - } - return v; + // This is a special case for dimension 1, because in that case, the right + // infinite full_cell is not correctly oriented... (sice its first vertex is the + // infinite one... + CGAL_precondition( is_infinite(s) ); + CGAL_precondition( 1 == current_dimension() ); + // FIXME: infinite vertex is NOT at index 0 a priori. But I'm not sure it's a problem here. + bool swap = (0 == s->neighbor(0)->index(s)); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + if( swap ) + { + s->swap_vertices(0, 1); + } + return v; } template < class TT, class TDS > @@ -910,31 +910,31 @@ typename Triangulation::Vertex_handle Triangulation ::insert_outside_convex_hull(const Point & p, Full_cell_handle s) { - if( 1 == current_dimension() ) - { - return insert_outside_convex_hull_1(p, s); - } - CGAL_precondition( is_infinite(s) ); - CGAL_assertion( current_dimension() >= 2 ); - std::vector simps; - simps.reserve(64); - std::back_insert_iterator > out(simps); - if( current_dimension() < maximal_dimension() ) - { - Outside_convex_hull_traversal_predicate - ochtp(*this, p, coaffine_orientation_predicate()); - tds().gather_full_cells(s, ochtp, out); - } - else - { - Orientation_d ori = geom_traits().orientation_d_object(); - Outside_convex_hull_traversal_predicate - ochtp(*this, p, ori); - tds().gather_full_cells(s, ochtp, out); - } - // FIXME: infinite vertex is NOT at index 0 a priori. - Vertex_handle v = insert_in_hole(p, simps.begin(), simps.end(), Facet(s, 0)); - return v; + if( 1 == current_dimension() ) + { + return insert_outside_convex_hull_1(p, s); + } + CGAL_precondition( is_infinite(s) ); + CGAL_assertion( current_dimension() >= 2 ); + std::vector simps; + simps.reserve(64); + std::back_insert_iterator > out(simps); + if( current_dimension() < maximal_dimension() ) + { + Outside_convex_hull_traversal_predicate + ochtp(*this, p, coaffine_orientation_predicate()); + tds().gather_full_cells(s, ochtp, out); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Outside_convex_hull_traversal_predicate + ochtp(*this, p, ori); + tds().gather_full_cells(s, ochtp, out); + } + // FIXME: infinite vertex is NOT at index 0 a priori. + Vertex_handle v = insert_in_hole(p, simps.begin(), simps.end(), Facet(s, 0)); + return v; } template < class TT, class TDS > @@ -942,21 +942,21 @@ typename Triangulation::Vertex_handle Triangulation ::insert_outside_affine_hull(const Point & p) { - CGAL_precondition( current_dimension() < maximal_dimension() ); - Vertex_handle v = tds().insert_increase_dimension(infinite_vertex()); - // reset the orientation predicate: - reset_flat_orientation(); - v->set_point(p); - if( current_dimension() >= 1 ) - { - // FIXME: infinite vertex is NOT at index 0 a priori. - Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); - Orientation o = orientation(s); - CGAL_assertion( COPLANAR != o ); - if( NEGATIVE == o ) - reorient_full_cells(); - } - return v; + CGAL_precondition( current_dimension() < maximal_dimension() ); + Vertex_handle v = tds().insert_increase_dimension(infinite_vertex()); + // reset the orientation predicate: + reset_flat_orientation(); + v->set_point(p); + if( current_dimension() >= 1 ) + { + // FIXME: infinite vertex is NOT at index 0 a priori. + Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Orientation o = orientation(s); + CGAL_assertion( COPLANAR != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + } + return v; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -967,181 +967,181 @@ template< typename OrientationPredicate > typename Triangulation::Full_cell_handle Triangulation ::do_locate( const Point & p, // query point - Locate_type & loc_type,// type of result (full_cell, face, vertex) - Face & face,// the face containing the query in its interior (when appropriate) - Facet & facet,// the facet containing the query in its interior (when appropriate) - const Full_cell_handle start// starting full_cell for the walk - , OrientationPredicate const& orientation_pred - ) const + Locate_type & loc_type,// type of result (full_cell, face, vertex) + Face & face,// the face containing the query in its interior (when appropriate) + Facet & facet,// the facet containing the query in its interior (when appropriate) + const Full_cell_handle start// starting full_cell for the walk + , OrientationPredicate const& orientation_pred + ) const { - const int cur_dim = current_dimension(); + const int cur_dim = current_dimension(); - if( cur_dim == -1 ) + if( cur_dim == -1 ) + { + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); + } + else if( cur_dim == 0 ) + { + Vertex_handle vit = infinite_full_cell()->neighbor(0)->vertex(0); + if( EQUAL != geom_traits().compare_lexicographically_d_object()(p, vit->point()) ) { - loc_type = OUTSIDE_AFFINE_HULL; - return Full_cell_handle(); + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); } - else if( cur_dim == 0 ) - { - Vertex_handle vit = infinite_full_cell()->neighbor(0)->vertex(0); - if( EQUAL != geom_traits().compare_lexicographically_d_object()(p, vit->point()) ) - { - loc_type = OUTSIDE_AFFINE_HULL; - return Full_cell_handle(); - } - else - { - loc_type = ON_VERTEX; - face.set_full_cell(vit->full_cell()); - face.set_index(0, 0); - return vit->full_cell(); - } - } - - Full_cell_handle s; - - // if we don't know where to start, we start from any bounded full_cell - if( Full_cell_handle() == start ) - // THE HACK THAT NOBODY SHOULD DO... BUT DIFFICULT TO WORK AROUND - // THIS... TODO: WORK AROUND IT - // FIXME: infinite vertex is NOT at index 0 a priori. - s = const_cast(this)->infinite_full_cell()->neighbor(0); else { - s = start; - if( is_infinite(s) ) - s = s->neighbor(0); // FIXME: index of infinite vertex is not zero ( not 0) + loc_type = ON_VERTEX; + face.set_full_cell(vit->full_cell()); + face.set_index(0, 0); + return vit->full_cell(); } + } - // Check if query |p| is outside the affine hull - if( cur_dim < maximal_dimension() ) + Full_cell_handle s; + + // if we don't know where to start, we start from any bounded full_cell + if( Full_cell_handle() == start ) + // THE HACK THAT NOBODY SHOULD DO... BUT DIFFICULT TO WORK AROUND + // THIS... TODO: WORK AROUND IT + // FIXME: infinite vertex is NOT at index 0 a priori. + s = const_cast(this)->infinite_full_cell()->neighbor(0); + else + { + s = start; + if( is_infinite(s) ) + s = s->neighbor(0); // FIXME: index of infinite vertex is not zero ( not 0) + } + + // Check if query |p| is outside the affine hull + if( cur_dim < maximal_dimension() ) + { + if( ! geom_traits().contained_in_affine_hull_d_object()( + points_begin(s), + points_begin(s) + current_dimension() + 1, + p) ) { - if( ! geom_traits().contained_in_affine_hull_d_object()( - points_begin(s), - points_begin(s) + current_dimension() + 1, - p) ) - { - loc_type = OUTSIDE_AFFINE_HULL; - return Full_cell_handle(); - } + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); } + } - // we remember the |previous|ly visited full_cell to avoid the evaluation - // of one |orientation| predicate - Full_cell_handle previous = Full_cell_handle(); - bool full_cell_not_found = true; - while(full_cell_not_found) // we walk until we locate the query point |p| + // we remember the |previous|ly visited full_cell to avoid the evaluation + // of one |orientation| predicate + Full_cell_handle previous = Full_cell_handle(); + bool full_cell_not_found = true; + while(full_cell_not_found) // we walk until we locate the query point |p| + { + #ifdef CGAL_TRIANGULATION_STATISTICS + ++walk_size_; + #endif + // For the remembering stochastic walk, we need to start trying + // with a random index: + int j, i = rng_.get_int(0, cur_dim); + // we check |p| against all the full_cell's hyperplanes in turn + + for(j = 0; j <= cur_dim; ++j, i = (i + 1) % (cur_dim + 1) ) { - #ifdef CGAL_TRIANGULATION_STATISTICS - ++walk_size_; - #endif - // For the remembering stochastic walk, we need to start trying - // with a random index: - int j, i = rng_.get_int(0, cur_dim); - // we check |p| against all the full_cell's hyperplanes in turn - - for(j = 0; j <= cur_dim; ++j, i = (i + 1) % (cur_dim + 1) ) - { - Full_cell_handle next = s->neighbor(i); - if( previous == next ) - { // no need to compute the orientation, we already know it - orientations_[i] = POSITIVE; - continue; // go to next full_cell's facet - } + Full_cell_handle next = s->neighbor(i); + if( previous == next ) + { // no need to compute the orientation, we already know it + orientations_[i] = POSITIVE; + continue; // go to next full_cell's facet + } - Substitute_point_in_vertex_iterator< - typename Full_cell::Vertex_handle_const_iterator> - spivi(s->vertex(i), &p); + Substitute_point_in_vertex_iterator< + typename Full_cell::Vertex_handle_const_iterator> + spivi(s->vertex(i), &p); - orientations_[i] = orientation_pred( - boost::make_transform_iterator(s->vertices_begin(), spivi), - boost::make_transform_iterator(s->vertices_begin() + cur_dim + 1, - spivi)); + orientations_[i] = orientation_pred( + boost::make_transform_iterator(s->vertices_begin(), spivi), + boost::make_transform_iterator(s->vertices_begin() + cur_dim + 1, + spivi)); - if( orientations_[i] != NEGATIVE ) - { - // from this facet's point of view, we are inside the - // full_cell or on its boundary, so we continue to next facet - continue; - } + if( orientations_[i] != NEGATIVE ) + { + // from this facet's point of view, we are inside the + // full_cell or on its boundary, so we continue to next facet + continue; + } - // At this point, we know that we have to jump to the |next| - // full_cell because orientation_[i] == NEGATIVE - previous = s; - s = next; - if( is_infinite(next) ) - { // we have arrived OUTSIDE the convex hull of the triangulation, - // so we stop the search - full_cell_not_found = false; - loc_type = OUTSIDE_CONVEX_HULL; - face.set_full_cell(s); - } - break; - } // end of the 'for' loop - if( ( cur_dim + 1 ) == j ) // we found the full_cell containing |p| - full_cell_not_found = false; - } - // Here, we know in which full_cell |p| is in. - // We now check more precisely where |p| landed: - // vertex, facet, face or full_cell. - if( ! is_infinite(s) ) - { + // At this point, we know that we have to jump to the |next| + // full_cell because orientation_[i] == NEGATIVE + previous = s; + s = next; + if( is_infinite(next) ) + { // we have arrived OUTSIDE the convex hull of the triangulation, + // so we stop the search + full_cell_not_found = false; + loc_type = OUTSIDE_CONVEX_HULL; face.set_full_cell(s); - int num(0); - int verts(0); - for(int i = 0; i < cur_dim; ++i) - { - if( orientations_[i] == COPLANAR ) - { - ++num; - facet = Facet(s, i); - } - else - face.set_index(verts++, i); - } - //-- We could put the if{}else{} below in the loop above, but then we would - // need to test if (verts < cur_dim) many times... we do it only once - // here: - if( orientations_[cur_dim] == COPLANAR ) - { - ++num; - facet = Facet(s, cur_dim); - } - else if( verts < cur_dim ) - face.set_index(verts, cur_dim); - //-- end of remark above // - if( 0 == num ) - { - loc_type = IN_FULL_CELL; - face.clear(); - } - else if( cur_dim == num ) - loc_type = ON_VERTEX; - else if( 1 == num ) - loc_type = IN_FACET; - else - loc_type = IN_FACE; + } + break; + } // end of the 'for' loop + if( ( cur_dim + 1 ) == j ) // we found the full_cell containing |p| + full_cell_not_found = false; + } + // Here, we know in which full_cell |p| is in. + // We now check more precisely where |p| landed: + // vertex, facet, face or full_cell. + if( ! is_infinite(s) ) + { + face.set_full_cell(s); + int num(0); + int verts(0); + for(int i = 0; i < cur_dim; ++i) + { + if( orientations_[i] == COPLANAR ) + { + ++num; + facet = Facet(s, i); + } + else + face.set_index(verts++, i); } - return s; + //-- We could put the if{}else{} below in the loop above, but then we would + // need to test if (verts < cur_dim) many times... we do it only once + // here: + if( orientations_[cur_dim] == COPLANAR ) + { + ++num; + facet = Facet(s, cur_dim); + } + else if( verts < cur_dim ) + face.set_index(verts, cur_dim); + //-- end of remark above // + if( 0 == num ) + { + loc_type = IN_FULL_CELL; + face.clear(); + } + else if( cur_dim == num ) + loc_type = ON_VERTEX; + else if( 1 == num ) + loc_type = IN_FACET; + else + loc_type = IN_FACE; + } + return s; } template < class TT, class TDS > typename Triangulation::Full_cell_handle Triangulation ::locate( const Point & p, // query point - Locate_type & loc_type,// type of result (full_cell, face, vertex) - Face & face,// the face containing the query in its interior (when appropriate) - Facet & facet,// the facet containing the query in its interior (when appropriate) - Full_cell_handle start// starting full_cell for the walk - ) const + Locate_type & loc_type,// type of result (full_cell, face, vertex) + Face & face,// the face containing the query in its interior (when appropriate) + Facet & facet,// the facet containing the query in its interior (when appropriate) + Full_cell_handle start// starting full_cell for the walk + ) const { - if( current_dimension() == maximal_dimension() ) - { - Orientation_d ori = geom_traits().orientation_d_object(); - return do_locate(p, loc_type, face, facet, start, ori); - } - else - return do_locate(p, loc_type, face, facet, start, coaffine_orientation_predicate()); + if( current_dimension() == maximal_dimension() ) + { + Orientation_d ori = geom_traits().orientation_d_object(); + return do_locate(p, loc_type, face, facet, start, ori); + } + else + return do_locate(p, loc_type, face, facet, start, coaffine_orientation_predicate()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1151,14 +1151,14 @@ template < class TT, class TDS > typename Triangulation::Full_cell_handle Triangulation ::locate( const Point & p, - Locate_type & loc_type, - Face & face, - Facet & facet, - Vertex_handle start) const + Locate_type & loc_type, + Face & face, + Facet & facet, + Vertex_handle start) const { - if( Vertex_handle() == start ) - start = infinite_vertex(); - return locate(p, loc_type, face, facet, start->full_cell()); + if( Vertex_handle() == start ) + start = infinite_vertex(); + return locate(p, loc_type, face, facet, start->full_cell()); } template < class TT, class TDS > @@ -1166,10 +1166,10 @@ typename Triangulation::Full_cell_handle Triangulation ::locate(const Point & p, Full_cell_handle s) const { - Locate_type lt; - Face face(maximal_dimension()); - Facet facet; - return locate(p, lt, face, facet, s); + Locate_type lt; + Face face(maximal_dimension()); + Facet facet; + return locate(p, lt, face, facet, s); } template < class TT, class TDS > @@ -1177,9 +1177,9 @@ typename Triangulation::Full_cell_handle Triangulation ::locate(const Point & p, Vertex_handle v) const { - if( Vertex_handle() != v ) - v = infinite_vertex(); - return this->locate(p, v->full_cell()); + if( Vertex_handle() != v ) + v = infinite_vertex(); + return this->locate(p, v->full_cell()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY @@ -1189,71 +1189,71 @@ bool Triangulation ::is_valid(bool verbose, int level) const { - if( ! tds().is_valid(verbose, level) ) - return false; + if( ! tds().is_valid(verbose, level) ) + return false; - Full_cell_const_iterator c; - if( current_dimension() < 0 ) - return true; - Orientation o; - for( c = full_cells_begin(); c != full_cells_end(); ++c ) - { - if( is_infinite(c) ) - { - if( current_dimension() > 1 ) - { - int i = c->index( infinite_vertex() ); - Full_cell_handle n = c->neighbor(i); - infinite_vertex()->set_point(n->vertex(c->mirror_index(i))->point()); - o = - orientation(c, true); - } - else - o = POSITIVE; - } - else - o = orientation(c, true); - if( NEGATIVE == o ) - { - if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); - return false; - } - if( COPLANAR == o ) - { - if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); - return false; - } - } + Full_cell_const_iterator c; + if( current_dimension() < 0 ) return true; + Orientation o; + for( c = full_cells_begin(); c != full_cells_end(); ++c ) + { + if( is_infinite(c) ) + { + if( current_dimension() > 1 ) + { + int i = c->index( infinite_vertex() ); + Full_cell_handle n = c->neighbor(i); + infinite_vertex()->set_point(n->vertex(c->mirror_index(i))->point()); + o = - orientation(c, true); + } + else + o = POSITIVE; + } + else + o = orientation(c, true); + if( NEGATIVE == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); + return false; + } + if( COPLANAR == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); + return false; + } + } + return true; } template < class TT, class TDS > bool Triangulation::are_incident_full_cells_valid(Vertex_const_handle v, bool verbose, int level) const { - if( current_dimension() <= 0 ) - return true; - typedef std::vector Simps; - Simps simps; - simps.reserve(64); - std::back_insert_iterator out(simps); - incident_full_cells(v, out); - typename Simps::const_iterator sit = simps.begin(); - for( ; sit != simps.end(); ++sit ) - { - if( is_infinite(*sit) ) - continue; - Orientation o = orientation(*sit); - if( NEGATIVE == o ) - { - if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); - return false; - } - if( COPLANAR == o ) - { - if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); - return false; - } - } + if( current_dimension() <= 0 ) return true; + typedef std::vector Simps; + Simps simps; + simps.reserve(64); + std::back_insert_iterator out(simps); + incident_full_cells(v, out); + typename Simps::const_iterator sit = simps.begin(); + for( ; sit != simps.end(); ++sit ) + { + if( is_infinite(*sit) ) + continue; + Orientation o = orientation(*sit); + if( NEGATIVE == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); + return false; + } + if( COPLANAR == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); + return false; + } + } + return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1272,43 +1272,43 @@ operator>>(std::istream & is, Triangulation & tr) // of vertices, plus the non combinatorial information on each full_cell // - the neighbors of each full_cell by their index in the preceding list { - typedef Triangulation T; - typedef typename T::Vertex_handle Vertex_handle; + typedef Triangulation T; + typedef typename T::Vertex_handle Vertex_handle; - // read current dimension and number of vertices - size_t n; - int cd; - if( is_ascii(is) ) - is >> cd >> n; - else - { - read(is, cd); - read(is, n, io_Read_write()); - } + // read current dimension and number of vertices + size_t n; + int cd; + if( is_ascii(is) ) + is >> cd >> n; + else + { + read(is, cd); + read(is, n, io_Read_write()); + } - CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation has too high dimension"); + CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation has too high dimension"); - tr.clear(); - tr.set_current_dimension(cd); + tr.clear(); + tr.set_current_dimension(cd); - if( n == 0 ) - return is; + if( n == 0 ) + return is; - std::vector vertices; - vertices.resize(n+1); - vertices[0] = tr.infinite_vertex(); - is >> (*vertices[0]); + std::vector vertices; + vertices.resize(n+1); + vertices[0] = tr.infinite_vertex(); + is >> (*vertices[0]); - // read the vertices: - size_t i(1); - while( i <= n ) - { - vertices[i] = tr.new_vertex(); - is >> (*vertices[i]); // read a vertex - ++i; - } + // read the vertices: + size_t i(1); + while( i <= n ) + { + vertices[i] = tr.new_vertex(); + is >> (*vertices[i]); // read a vertex + ++i; + } - // now, read the combinatorial information + // now, read the combinatorial information return tr.tds().read_full_cells(is, vertices); } @@ -1324,41 +1324,41 @@ operator<<(std::ostream & os, const Triangulation & tr) // of vertices, plus the non combinatorial information on each full_cell // - the neighbors of each full_cell by their index in the preceding list { - typedef Triangulation T; - typedef typename T::Vertex_const_handle Vertex_handle; - typedef typename T::Vertex_const_iterator Vertex_iterator; + typedef Triangulation T; + typedef typename T::Vertex_const_handle Vertex_handle; + typedef typename T::Vertex_const_iterator Vertex_iterator; - // outputs dimensions and number of vertices - size_t n = tr.number_of_vertices(); - if( is_ascii(os) ) - os << tr.current_dimension() << std::endl << n << std::endl; - else - { - write(os, tr.current_dimension()); - write(os, n, io_Read_write()); - } + // outputs dimensions and number of vertices + size_t n = tr.number_of_vertices(); + if( is_ascii(os) ) + os << tr.current_dimension() << std::endl << n << std::endl; + else + { + write(os, tr.current_dimension()); + write(os, n, io_Read_write()); + } - if( n == 0 ) - return os; + if( n == 0 ) + return os; - size_t i(0); - // write the vertices - std::map index_of_vertex; + size_t i(0); + // write the vertices + std::map index_of_vertex; - // infinite vertex has index 0 (among all the vertices) - index_of_vertex[tr.infinite_vertex()] = i++; - os << *tr.infinite_vertex(); - for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it ) - { - if( tr.is_infinite(it) ) - continue; - os << *it; // write the vertex - index_of_vertex[it] = i++; - } - CGAL_assertion( i == n+1 ); + // infinite vertex has index 0 (among all the vertices) + index_of_vertex[tr.infinite_vertex()] = i++; + os << *tr.infinite_vertex(); + for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it ) + { + if( tr.is_infinite(it) ) + continue; + os << *it; // write the vertex + index_of_vertex[it] = i++; + } + CGAL_assertion( i == n+1 ); - // output the combinatorial information - return tr.tds().write_full_cells(os, index_of_vertex); + // output the combinatorial information + return tr.tds().write_full_cells(os, index_of_vertex); } } //namespace CGAL diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index b1d3912f4a7..0b0674a263c 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -37,577 +37,577 @@ namespace CGAL { template< class Dimen, - class Vb = Default, - class Fcb = Default > + class Vb = Default, + class Fcb = Default > class Triangulation_data_structure { - typedef Triangulation_data_structure Self; - typedef typename Default::Get >::type V_base; - typedef typename Default::Get >::type FC_base; + typedef Triangulation_data_structure Self; + typedef typename Default::Get >::type V_base; + typedef typename Default::Get >::type FC_base; public: - typedef typename V_base::template Rebind_TDS::Other Vertex; /* Concept */ - typedef typename FC_base::template Rebind_TDS::Other Full_cell; /* Concept */ + typedef typename V_base::template Rebind_TDS::Other Vertex; /* Concept */ + typedef typename FC_base::template Rebind_TDS::Other Full_cell; /* Concept */ // Tools to change the Vertex and Cell types of the TDS. template < typename Vb2 > struct Rebind_vertex { - typedef Triangulation_data_structure Other; + typedef Triangulation_data_structure Other; }; template < typename Fcb2 > struct Rebind_full_cell { - typedef Triangulation_data_structure Other; + typedef Triangulation_data_structure Other; }; - // we want to store an object of this class in every Full_cell: - class Full_cell_data - { - unsigned char bits_; - public: - Full_cell_data() : bits_(0) {} - Full_cell_data(const Full_cell_data & fcd) : bits_(fcd.bits_) {} + // we want to store an object of this class in every Full_cell: + class Full_cell_data + { + unsigned char bits_; + public: + Full_cell_data() : bits_(0) {} + Full_cell_data(const Full_cell_data & fcd) : bits_(fcd.bits_) {} - void clear() { bits_ = 0; } - void mark_visited() { bits_ = 1; } - void clear_visited() { bits_ = 0; } + void clear() { bits_ = 0; } + void mark_visited() { bits_ = 1; } + void clear_visited() { bits_ = 0; } - bool is_clear() const { return bits_ == 0; } - bool is_visited() const { return bits_ == 1; } - // WARNING: if we use more bits and several bits can be set at once, - // then make sure to use bitwise operation above, instead of direct - // affectation. - }; + bool is_clear() const { return bits_ == 0; } + bool is_visited() const { return bits_ == 1; } + // WARNING: if we use more bits and several bits can be set at once, + // then make sure to use bitwise operation above, instead of direct + // affectation. + }; protected: - typedef Compact_container Vertex_container; - typedef Compact_container Full_cell_container; + typedef Compact_container Vertex_container; + typedef Compact_container Full_cell_container; public: - typedef Dimen Maximal_dimension; + typedef Dimen Maximal_dimension; - typedef typename Vertex_container::size_type size_type; /* Concept */ - typedef typename Vertex_container::difference_type difference_type; /* Concept */ + typedef typename Vertex_container::size_type size_type; /* Concept */ + typedef typename Vertex_container::difference_type difference_type; /* Concept */ - typedef typename Vertex_container::iterator Vertex_handle; /* Concept */ - typedef typename Vertex_container::iterator Vertex_iterator; /* Concept */ - typedef typename Vertex_container::const_iterator Vertex_const_handle; - typedef typename Vertex_container::const_iterator Vertex_const_iterator; + typedef typename Vertex_container::iterator Vertex_handle; /* Concept */ + typedef typename Vertex_container::iterator Vertex_iterator; /* Concept */ + typedef typename Vertex_container::const_iterator Vertex_const_handle; + typedef typename Vertex_container::const_iterator Vertex_const_iterator; - typedef typename Full_cell_container::iterator Full_cell_handle; /* Concept */ - typedef typename Full_cell_container::iterator Full_cell_iterator; /* Concept */ - typedef typename Full_cell_container::const_iterator Full_cell_const_handle; - typedef typename Full_cell_container::const_iterator Full_cell_const_iterator; + typedef typename Full_cell_container::iterator Full_cell_handle; /* Concept */ + typedef typename Full_cell_container::iterator Full_cell_iterator; /* Concept */ + typedef typename Full_cell_container::const_iterator Full_cell_const_handle; + typedef typename Full_cell_container::const_iterator Full_cell_const_iterator; - typedef internal::Triangulation:: - Triangulation_ds_facet_iterator Facet_iterator; /* Concept */ + typedef internal::Triangulation:: + Triangulation_ds_facet_iterator Facet_iterator; /* Concept */ - /* The 2 types defined below, |Facet| and |Rotor| are used when traversing - the boundary `B' of the union of a set of full cells. |Rotor| makes it - easy to rotate around itself, in the search of neighbors in `B' (see - |rotate_rotor| and |insert_in_tagged_hole|) */ + /* The 2 types defined below, |Facet| and |Rotor| are used when traversing + the boundary `B' of the union of a set of full cells. |Rotor| makes it + easy to rotate around itself, in the search of neighbors in `B' (see + |rotate_rotor| and |insert_in_tagged_hole|) */ - // A co-dimension 1 sub-simplex. - class Facet /* Concept */ - { - Full_cell_handle full_cell_; - int index_of_covertex_; - public: - Facet() : full_cell_(), index_of_covertex_(0) {} - Facet(Full_cell_handle f, int i) : full_cell_(f), index_of_covertex_(i) {} - Full_cell_handle full_cell() const { return full_cell_; } - int index_of_covertex() const { return index_of_covertex_; } - }; + // A co-dimension 1 sub-simplex. + class Facet /* Concept */ + { + Full_cell_handle full_cell_; + int index_of_covertex_; + public: + Facet() : full_cell_(), index_of_covertex_(0) {} + Facet(Full_cell_handle f, int i) : full_cell_(f), index_of_covertex_(i) {} + Full_cell_handle full_cell() const { return full_cell_; } + int index_of_covertex() const { return index_of_covertex_; } + }; - // A co-dimension 2 sub-simplex. called a Rotor because we can rotate - // the two "covertices" around the sub-simplex. Useful for traversing the - // boundary of a hole. NOT DOCUMENTED - class Rotor : public Facet - { - int index_of_second_covertex_; - public: - Rotor() : Facet(), index_of_second_covertex_(0) {} - Rotor(Full_cell_handle f, int first, int second) : Facet(f, first), index_of_second_covertex_(second) {} - int index_of_second_covertex() const { return index_of_second_covertex_; } - }; + // A co-dimension 2 sub-simplex. called a Rotor because we can rotate + // the two "covertices" around the sub-simplex. Useful for traversing the + // boundary of a hole. NOT DOCUMENTED + class Rotor : public Facet + { + int index_of_second_covertex_; + public: + Rotor() : Facet(), index_of_second_covertex_(0) {} + Rotor(Full_cell_handle f, int first, int second) : Facet(f, first), index_of_second_covertex_(second) {} + int index_of_second_covertex() const { return index_of_second_covertex_; } + }; - typedef Triangulation_face Face; /* Concept */ + typedef Triangulation_face Face; /* Concept */ protected: // DATA MEMBERS - int dmax_, dcur_; // dimension of the current triangulation - Vertex_container vertices_; // list of all vertices - Full_cell_container full_cells_; // list of all full cells + int dmax_, dcur_; // dimension of the current triangulation + Vertex_container vertices_; // list of all vertices + Full_cell_container full_cells_; // list of all full cells private: - void clean_dynamic_memory() - { - vertices_.clear(); - full_cells_.clear(); - } + void clean_dynamic_memory() + { + vertices_.clear(); + full_cells_.clear(); + } - template < class Dim_tag > - struct get_maximal_dimension - { - static int value(const int D) { return D; } - }; - // specialization - template < int D > - struct get_maximal_dimension > - { - static int value(const int) { return D; } - }; + template < class Dim_tag > + struct get_maximal_dimension + { + static int value(const int D) { return D; } + }; + // specialization + template < int D > + struct get_maximal_dimension > + { + static int value(const int) { return D; } + }; public: - Triangulation_data_structure( int dim=0) /* Concept */ - : dmax_(get_maximal_dimension::value(dim)), dcur_(-2), - vertices_(), full_cells_() - { - CGAL_assertion_msg(dmax_ > 0, "maximal dimension must be positive."); - } + Triangulation_data_structure( int dim=0) /* Concept */ + : dmax_(get_maximal_dimension::value(dim)), dcur_(-2), + vertices_(), full_cells_() + { + CGAL_assertion_msg(dmax_ > 0, "maximal dimension must be positive."); + } - ~Triangulation_data_structure() - { - clean_dynamic_memory(); - } + ~Triangulation_data_structure() + { + clean_dynamic_memory(); + } - Triangulation_data_structure(const Triangulation_data_structure & tds) - : dmax_(tds.dmax_), dcur_(tds.dcur_), - vertices_(tds.vertices_), full_cells_(tds.full_cells_) + Triangulation_data_structure(const Triangulation_data_structure & tds) + : dmax_(tds.dmax_), dcur_(tds.dcur_), + vertices_(tds.vertices_), full_cells_(tds.full_cells_) + { + typedef std::map V_map; + typedef std::map C_map; + V_map vmap; + C_map cmap; + Vertex_const_iterator vfrom = tds.vertices_begin(); + Vertex_iterator vto = vertices_begin(); + Full_cell_const_iterator cfrom = tds.full_cells_begin(); + Full_cell_iterator cto = full_cells_begin(); + while( vfrom != tds.vertices_end() ) + vmap[vfrom++] = vto++; + while( cfrom != tds.full_cells_end() ) + cmap[cfrom++] = cto++; + cto = full_cells_begin(); + while( cto != full_cells_end() ) { - typedef std::map V_map; - typedef std::map C_map; - V_map vmap; - C_map cmap; - Vertex_const_iterator vfrom = tds.vertices_begin(); - Vertex_iterator vto = vertices_begin(); - Full_cell_const_iterator cfrom = tds.full_cells_begin(); - Full_cell_iterator cto = full_cells_begin(); - while( vfrom != tds.vertices_end() ) - vmap[vfrom++] = vto++; - while( cfrom != tds.full_cells_end() ) - cmap[cfrom++] = cto++; - cto = full_cells_begin(); - while( cto != full_cells_end() ) - { - for( int i = 0; i <= current_dimension(); ++i ) - { - associate_vertex_with_full_cell(cto, i, vmap[cto->vertex(i)]); - cto->set_neighbor(i, cmap[cto->neighbor(i)]); - } - ++cto; - } + for( int i = 0; i <= current_dimension(); ++i ) + { + associate_vertex_with_full_cell(cto, i, vmap[cto->vertex(i)]); + cto->set_neighbor(i, cmap[cto->neighbor(i)]); + } + ++cto; } + } - // QUERIES + // QUERIES protected: - bool check_range(const int i) const + bool check_range(const int i) const + { + if( current_dimension() < 0 ) { - if( current_dimension() < 0 ) - { - return (0 == i); - } - return ( (0 <= i) && (i <= current_dimension()) ); + return (0 == i); } + return ( (0 <= i) && (i <= current_dimension()) ); + } public: - /* returns the current dimension of the full cells in the triangulation. */ - int maximal_dimension() const { return dmax_; } /* Concept */ - int current_dimension() const { return dcur_; } /* Concept */ + /* returns the current dimension of the full cells in the triangulation. */ + int maximal_dimension() const { return dmax_; } /* Concept */ + int current_dimension() const { return dcur_; } /* Concept */ - size_type number_of_vertices() const /* Concept */ - { - return this->vertices_.size(); - } - size_type number_of_full_cells() const /* Concept */ - { - return this->full_cells_.size(); - } + size_type number_of_vertices() const /* Concept */ + { + return this->vertices_.size(); + } + size_type number_of_full_cells() const /* Concept */ + { + return this->full_cells_.size(); + } - bool empty() const /* Concept */ - { - return current_dimension() == -2; - } + bool empty() const /* Concept */ + { + return current_dimension() == -2; + } - Vertex_container & vertices() { return vertices_; } - const Vertex_container & vertices() const { return vertices_; } - Full_cell_container & full_cells() { return full_cells_; } - const Full_cell_container & full_cells() const { return full_cells_; } + Vertex_container & vertices() { return vertices_; } + const Vertex_container & vertices() const { return vertices_; } + Full_cell_container & full_cells() { return full_cells_; } + const Full_cell_container & full_cells() const { return full_cells_; } - Vertex_handle vertex(const Full_cell_handle s, const int i) const /* Concept */ - { - CGAL_precondition(s != Full_cell_handle() && check_range(i)); - return s->vertex(i); - } + Vertex_handle vertex(const Full_cell_handle s, const int i) const /* Concept */ + { + CGAL_precondition(s != Full_cell_handle() && check_range(i)); + return s->vertex(i); + } - Vertex_const_handle vertex(const Full_cell_const_handle s, const int i) const /* Concept */ - { - CGAL_precondition(s != Full_cell_handle() && check_range(i)); - return s->vertex(i); - } + Vertex_const_handle vertex(const Full_cell_const_handle s, const int i) const /* Concept */ + { + CGAL_precondition(s != Full_cell_handle() && check_range(i)); + return s->vertex(i); + } - bool is_vertex(const Vertex_const_handle & v) const /* Concept */ - { - if( Vertex_const_handle() == v ) - return false; - Vertex_const_iterator vit = vertices_begin(); - while( vit != vertices_end() && ( v != vit ) ) - ++vit; - return v == vit; - } + bool is_vertex(const Vertex_const_handle & v) const /* Concept */ + { + if( Vertex_const_handle() == v ) + return false; + Vertex_const_iterator vit = vertices_begin(); + while( vit != vertices_end() && ( v != vit ) ) + ++vit; + return v == vit; + } - bool is_full_cell(const Full_cell_const_handle & s) const /* Concept */ - { - if( Full_cell_const_handle() == s ) - return false; - Full_cell_const_iterator sit = full_cells_begin(); - while( sit != full_cells_end() && ( s != sit ) ) - ++sit; - return s == sit; - } + bool is_full_cell(const Full_cell_const_handle & s) const /* Concept */ + { + if( Full_cell_const_handle() == s ) + return false; + Full_cell_const_iterator sit = full_cells_begin(); + while( sit != full_cells_end() && ( s != sit ) ) + ++sit; + return s == sit; + } - Full_cell_handle full_cell(const Vertex_handle v) const /* Concept */ - { - CGAL_precondition(v != Vertex_handle()); - return v->full_cell(); - } + Full_cell_handle full_cell(const Vertex_handle v) const /* Concept */ + { + CGAL_precondition(v != Vertex_handle()); + return v->full_cell(); + } - Full_cell_const_handle full_cell(const Vertex_const_handle v) const /* Concept */ - { - CGAL_precondition(Vertex_const_handle() != v); - return v->full_cell(); - } + Full_cell_const_handle full_cell(const Vertex_const_handle v) const /* Concept */ + { + CGAL_precondition(Vertex_const_handle() != v); + return v->full_cell(); + } - Full_cell_handle neighbor(const Full_cell_handle s, const int i) const /* Concept */ - { - CGAL_precondition(Full_cell_handle() != s && check_range(i)); - return s->neighbor(i); - } + Full_cell_handle neighbor(const Full_cell_handle s, const int i) const /* Concept */ + { + CGAL_precondition(Full_cell_handle() != s && check_range(i)); + return s->neighbor(i); + } - Full_cell_const_handle neighbor(const Full_cell_const_handle s, const int i) const/* Concept */ - { - CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); - return s->neighbor(i); - } + Full_cell_const_handle neighbor(const Full_cell_const_handle s, const int i) const/* Concept */ + { + CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); + return s->neighbor(i); + } - int mirror_index(const Full_cell_handle s, const int i) const /* Concept */ - { - CGAL_precondition(Full_cell_handle() != s && check_range(i)); - return s->mirror_index(i); - } + int mirror_index(const Full_cell_handle s, const int i) const /* Concept */ + { + CGAL_precondition(Full_cell_handle() != s && check_range(i)); + return s->mirror_index(i); + } - int mirror_index(const Full_cell_const_handle s, const int i) const - { - CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); /* Concept */ - return s->mirror_index(i); - } + int mirror_index(const Full_cell_const_handle s, const int i) const + { + CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); /* Concept */ + return s->mirror_index(i); + } - int mirror_vertex(const Full_cell_handle s, const int i) const /* Concept */ - { - CGAL_precondition(Full_cell_handle() != s && check_range(i)); - return s->mirror_vertex(i); - } + int mirror_vertex(const Full_cell_handle s, const int i) const /* Concept */ + { + CGAL_precondition(Full_cell_handle() != s && check_range(i)); + return s->mirror_vertex(i); + } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FACETS OPERATIONS + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FACETS OPERATIONS - // works for Face_ = Facet and Face_ = Rotor. - // NOT DOCUMENTED for the Rotor case... - template< typename Face_ > - Full_cell_handle full_cell(const Face_ & f) const /* Concept */ - { - return f.full_cell(); - } + // works for Face_ = Facet and Face_ = Rotor. + // NOT DOCUMENTED for the Rotor case... + template< typename Face_ > + Full_cell_handle full_cell(const Face_ & f) const /* Concept */ + { + return f.full_cell(); + } - // works for Face_ = Facet and Face_ = Rotor. - // NOT DOCUMENTED for the Rotor case... - template< class Face_ > - int index_of_covertex(const Face_ & f) const /* Concept */ - { - return f.index_of_covertex(); - } + // works for Face_ = Facet and Face_ = Rotor. + // NOT DOCUMENTED for the Rotor case... + template< class Face_ > + int index_of_covertex(const Face_ & f) const /* Concept */ + { + return f.index_of_covertex(); + } - // NOT DOCUMENTED - // A Rotor has two covertices - int index_of_second_covertex(const Rotor & f) const - { - return f.index_of_second_covertex(); - } + // NOT DOCUMENTED + // A Rotor has two covertices + int index_of_second_covertex(const Rotor & f) const + { + return f.index_of_second_covertex(); + } - // works for Face_ = Facet and Face_ = Rotor. - // NOT DOCUMENTED... - template< class Face_ > - bool is_boundary_facet(const Face_ & f) const - { - if( get_visited(neighbor(full_cell(f), index_of_covertex(f))) ) - return false; - if( ! get_visited(full_cell(f)) ) - return false; - return true; - } + // works for Face_ = Facet and Face_ = Rotor. + // NOT DOCUMENTED... + template< class Face_ > + bool is_boundary_facet(const Face_ & f) const + { + if( get_visited(neighbor(full_cell(f), index_of_covertex(f))) ) + return false; + if( ! get_visited(full_cell(f)) ) + return false; + return true; + } - // NOT DOCUMENTED... - Rotor rotate_rotor(Rotor & f) - { - int opposite = mirror_index(full_cell(f), index_of_covertex(f)); - Full_cell_handle s = neighbor(full_cell(f), index_of_covertex(f)); - int new_second = s->index(vertex(full_cell(f), index_of_second_covertex(f))); - return Rotor(s, new_second, opposite); - } + // NOT DOCUMENTED... + Rotor rotate_rotor(Rotor & f) + { + int opposite = mirror_index(full_cell(f), index_of_covertex(f)); + Full_cell_handle s = neighbor(full_cell(f), index_of_covertex(f)); + int new_second = s->index(vertex(full_cell(f), index_of_second_covertex(f))); + return Rotor(s, new_second, opposite); + } - // NICE UPDATE OPERATIONS + // NICE UPDATE OPERATIONS protected: - void do_insert_increase_dimension(const Vertex_handle, const Vertex_handle); + void do_insert_increase_dimension(const Vertex_handle, const Vertex_handle); public: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS - Vertex_handle collapse_face(const Face &); /* Concept */ - void remove_decrease_dimension(Vertex_handle, Vertex_handle); /* Concept */ + Vertex_handle collapse_face(const Face &); /* Concept */ + void remove_decrease_dimension(Vertex_handle, Vertex_handle); /* Concept */ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS - Vertex_handle insert_in_full_cell(Full_cell_handle); /* Concept */ - Vertex_handle insert_in_face(const Face &); /* Concept */ - Vertex_handle insert_in_facet(const Facet &); /* Concept */ - template< typename Forward_iterator > - Vertex_handle insert_in_hole(Forward_iterator, const Forward_iterator, Facet); /* Concept */ - template< typename Forward_iterator, typename OutputIterator > - Vertex_handle insert_in_hole(Forward_iterator, const Forward_iterator, Facet, OutputIterator); /* Concept */ + Vertex_handle insert_in_full_cell(Full_cell_handle); /* Concept */ + Vertex_handle insert_in_face(const Face &); /* Concept */ + Vertex_handle insert_in_facet(const Facet &); /* Concept */ + template< typename Forward_iterator > + Vertex_handle insert_in_hole(Forward_iterator, const Forward_iterator, Facet); /* Concept */ + template< typename Forward_iterator, typename OutputIterator > + Vertex_handle insert_in_hole(Forward_iterator, const Forward_iterator, Facet, OutputIterator); /* Concept */ - template< typename OutputIterator > - Full_cell_handle insert_in_tagged_hole(Vertex_handle, Facet, OutputIterator); + template< typename OutputIterator > + Full_cell_handle insert_in_tagged_hole(Vertex_handle, Facet, OutputIterator); - Vertex_handle insert_increase_dimension(Vertex_handle=Vertex_handle()); /* Concept */ + Vertex_handle insert_increase_dimension(Vertex_handle=Vertex_handle()); /* Concept */ private: - // NOT DOCUMENTED - void clear_visited_marks(Full_cell_handle) const; + // NOT DOCUMENTED + void clear_visited_marks(Full_cell_handle) const; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DANGEROUS UPDATE OPERATIONS + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DANGEROUS UPDATE OPERATIONS private: - // NOT DOCUMENTED - template< typename FCH > // FCH = Full_cell_[const_]handle - bool get_visited(FCH c) const - { - return c->tds_data().is_visited(); - } + // NOT DOCUMENTED + template< typename FCH > // FCH = Full_cell_[const_]handle + bool get_visited(FCH c) const + { + return c->tds_data().is_visited(); + } - // NOT DOCUMENTED - template< typename FCH > // FCH = Full_cell_[const_]handle - void set_visited(FCH c, bool m) const - { - if( m ) - c->tds_data().mark_visited(); - else - c->tds_data().clear_visited(); - } + // NOT DOCUMENTED + template< typename FCH > // FCH = Full_cell_[const_]handle + void set_visited(FCH c, bool m) const + { + if( m ) + c->tds_data().mark_visited(); + else + c->tds_data().clear_visited(); + } public: - void clear() /* Concept */ - { - clean_dynamic_memory(); - dcur_ = -2; - } + void clear() /* Concept */ + { + clean_dynamic_memory(); + dcur_ = -2; + } - void set_current_dimension(const int d) /* Concept */ - { - CGAL_precondition(-2<=d && d<=maximal_dimension()); - dcur_ = d; - } + void set_current_dimension(const int d) /* Concept */ + { + CGAL_precondition(-2<=d && d<=maximal_dimension()); + dcur_ = d; + } - Full_cell_handle new_full_cell(const Full_cell_handle s) - { - return full_cells_.emplace(*s); - } + Full_cell_handle new_full_cell(const Full_cell_handle s) + { + return full_cells_.emplace(*s); + } - Full_cell_handle new_full_cell() /* Concept */ - { - return full_cells_.emplace(dmax_); - } + Full_cell_handle new_full_cell() /* Concept */ + { + return full_cells_.emplace(dmax_); + } - void delete_full_cell(Full_cell_handle s) /* Concept */ - { - CGAL_precondition(Full_cell_handle() != s); - // CGAL_expensive_precondition(is_full_cell(s)); - full_cells_.erase(s); - } + void delete_full_cell(Full_cell_handle s) /* Concept */ + { + CGAL_precondition(Full_cell_handle() != s); + // CGAL_expensive_precondition(is_full_cell(s)); + full_cells_.erase(s); + } - template< typename Forward_iterator > - void delete_full_cells(Forward_iterator start, Forward_iterator end) /* Concept */ - { - Forward_iterator s = start; - while( s != end ) - full_cells_.erase(*s++); - } + template< typename Forward_iterator > + void delete_full_cells(Forward_iterator start, Forward_iterator end) /* Concept */ + { + Forward_iterator s = start; + while( s != end ) + full_cells_.erase(*s++); + } - template< class T > - Vertex_handle new_vertex( const T & t ) - { - return vertices_.emplace(t); - } + template< class T > + Vertex_handle new_vertex( const T & t ) + { + return vertices_.emplace(t); + } - Vertex_handle new_vertex() /* Concept */ - { - return vertices_.emplace(); - } + Vertex_handle new_vertex() /* Concept */ + { + return vertices_.emplace(); + } - void delete_vertex(Vertex_handle v) /* Concept */ - { - CGAL_precondition( Vertex_handle() != v ); - vertices_.erase(v); - } + void delete_vertex(Vertex_handle v) /* Concept */ + { + CGAL_precondition( Vertex_handle() != v ); + vertices_.erase(v); + } - void associate_vertex_with_full_cell(Full_cell_handle s, const int i, Vertex_handle v) /* Concept */ - { - CGAL_precondition(check_range(i)); - CGAL_precondition(s != Full_cell_handle()); - CGAL_precondition(v != Vertex_handle()); - s->set_vertex(i, v); - v->set_full_cell(s); - } + void associate_vertex_with_full_cell(Full_cell_handle s, const int i, Vertex_handle v) /* Concept */ + { + CGAL_precondition(check_range(i)); + CGAL_precondition(s != Full_cell_handle()); + CGAL_precondition(v != Vertex_handle()); + s->set_vertex(i, v); + v->set_full_cell(s); + } - void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) /* Concept */ - { - CGAL_precondition(check_range(i)); - CGAL_precondition(check_range(j)); - CGAL_precondition(s != Full_cell_handle()); - CGAL_precondition(s1 != Full_cell_handle()); - s->set_neighbor(i, s1); - s1->set_neighbor(j, s); - s->set_mirror_index(i, j); - s1->set_mirror_index(j, i); - } + void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) /* Concept */ + { + CGAL_precondition(check_range(i)); + CGAL_precondition(check_range(j)); + CGAL_precondition(s != Full_cell_handle()); + CGAL_precondition(s1 != Full_cell_handle()); + s->set_neighbor(i, s1); + s1->set_neighbor(j, s); + s->set_mirror_index(i, j); + s1->set_mirror_index(j, i); + } - // SANITY CHECKS + // SANITY CHECKS - bool is_valid(bool = true, int = 0) const; /* Concept */ + bool is_valid(bool = true, int = 0) const; /* Concept */ - // NOT DOCUMENTED - template< class OutStream> void write_graph(OutStream &); + // NOT DOCUMENTED + template< class OutStream> void write_graph(OutStream &); - Vertex_iterator vertices_begin() { return vertices_.begin(); } /* Concept */ - Vertex_iterator vertices_end() { return vertices_.end(); } /* Concept */ - Full_cell_iterator full_cells_begin() { return full_cells_.begin(); } /* Concept */ - Full_cell_iterator full_cells_end() { return full_cells_.end(); } /* Concept */ + Vertex_iterator vertices_begin() { return vertices_.begin(); } /* Concept */ + Vertex_iterator vertices_end() { return vertices_.end(); } /* Concept */ + Full_cell_iterator full_cells_begin() { return full_cells_.begin(); } /* Concept */ + Full_cell_iterator full_cells_end() { return full_cells_.end(); } /* Concept */ - Vertex_const_iterator vertices_begin() const { return vertices_.begin(); } /* Concept */ - Vertex_const_iterator vertices_end() const { return vertices_.end(); } /* Concept */ - Full_cell_const_iterator full_cells_begin() const { return full_cells_.begin(); } /* Concept */ - Full_cell_const_iterator full_cells_end() const { return full_cells_.end(); } /* Concept */ + Vertex_const_iterator vertices_begin() const { return vertices_.begin(); } /* Concept */ + Vertex_const_iterator vertices_end() const { return vertices_.end(); } /* Concept */ + Full_cell_const_iterator full_cells_begin() const { return full_cells_.begin(); } /* Concept */ + Full_cell_const_iterator full_cells_end() const { return full_cells_.end(); } /* Concept */ - Facet_iterator facets_begin() /* Concept */ - { - if( current_dimension() <= 0 ) - return facets_end(); - return Facet_iterator(*this); - } - Facet_iterator facets_end() /* Concept */ - { - return Facet_iterator(*this, 0); - } + Facet_iterator facets_begin() /* Concept */ + { + if( current_dimension() <= 0 ) + return facets_end(); + return Facet_iterator(*this); + } + Facet_iterator facets_end() /* Concept */ + { + return Facet_iterator(*this, 0); + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - FULL CELL GATHERING - // a traversal predicate for gathering full_cells incident to a given face - // ``incident'' means that the given face is a subface of the full_cell - class Incident_full_cell_traversal_predicate + // a traversal predicate for gathering full_cells incident to a given face + // ``incident'' means that the given face is a subface of the full_cell + class Incident_full_cell_traversal_predicate + { + const Face & f_; + int dim_; + const Triangulation_data_structure & tds_; + public: + Incident_full_cell_traversal_predicate(const Triangulation_data_structure & tds, + const Face & f) + : f_(f), tds_(tds) { - const Face & f_; - int dim_; - const Triangulation_data_structure & tds_; - public: - Incident_full_cell_traversal_predicate(const Triangulation_data_structure & tds, - const Face & f) - : f_(f), tds_(tds) - { - dim_ = f.face_dimension(); - } - bool operator()(const Facet & facet) const - { - Vertex_handle v = tds_.full_cell(facet)->vertex(tds_.index_of_covertex(facet)); - for( int i = 0; i <= dim_; ++i ) - { - if( v == f_.vertex(i) ) - return false; - } + dim_ = f.face_dimension(); + } + bool operator()(const Facet & facet) const + { + Vertex_handle v = tds_.full_cell(facet)->vertex(tds_.index_of_covertex(facet)); + for( int i = 0; i <= dim_; ++i ) + { + if( v == f_.vertex(i) ) + return false; + } + return true; + } + }; + + // a traversal predicate for gathering full_cells having a given face as subface + class Star_traversal_predicate + { + const Face & f_; + int dim_; + const Triangulation_data_structure & tds_; + public: + Star_traversal_predicate(const Triangulation_data_structure & tds, + const Face & f) + : f_(f), tds_(tds) + { + dim_ = f.face_dimension(); + } + bool operator()(const Facet & facet) const + { + Full_cell_handle s = tds_.full_cell(facet)->neighbor(tds_.index_of_covertex(facet)); + for( int j = 0; j <= tds_.current_dimension(); ++j ) + { + for( int i = 0; i <= dim_; ++i ) + if( s->vertex(j) == f_.vertex(i) ) return true; - } - }; + } + return false; + } + }; - // a traversal predicate for gathering full_cells having a given face as subface - class Star_traversal_predicate - { - const Face & f_; - int dim_; - const Triangulation_data_structure & tds_; - public: - Star_traversal_predicate(const Triangulation_data_structure & tds, - const Face & f) - : f_(f), tds_(tds) - { - dim_ = f.face_dimension(); - } - bool operator()(const Facet & facet) const - { - Full_cell_handle s = tds_.full_cell(facet)->neighbor(tds_.index_of_covertex(facet)); - for( int j = 0; j <= tds_.current_dimension(); ++j ) - { - for( int i = 0; i <= dim_; ++i ) - if( s->vertex(j) == f_.vertex(i) ) - return true; - } - return false; - } - }; - - template< typename TraversalPredicate, typename OutputIterator > - Facet gather_full_cells(Full_cell_handle, TraversalPredicate &, OutputIterator &) const; /* Concept */ - template< typename OutputIterator > - OutputIterator incident_full_cells(const Face &, OutputIterator) const; /* Concept */ - template< typename OutputIterator > - OutputIterator incident_full_cells(Vertex_const_handle, OutputIterator) const; /* Concept */ - template< typename OutputIterator > - OutputIterator star(const Face &, OutputIterator) const; /* Concept */ + template< typename TraversalPredicate, typename OutputIterator > + Facet gather_full_cells(Full_cell_handle, TraversalPredicate &, OutputIterator &) const; /* Concept */ + template< typename OutputIterator > + OutputIterator incident_full_cells(const Face &, OutputIterator) const; /* Concept */ + template< typename OutputIterator > + OutputIterator incident_full_cells(Vertex_const_handle, OutputIterator) const; /* Concept */ + template< typename OutputIterator > + OutputIterator star(const Face &, OutputIterator) const; /* Concept */ #ifndef CGAL_CFG_NO_CPP0X_DEFAULT_TEMPLATE_ARGUMENTS_FOR_FUNCTION_TEMPLATES - template< typename OutputIterator, typename Comparator = std::less > - OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator()) - { - return incident_faces(v, dim, out, cmp, true); - } - template< typename OutputIterator, typename Comparator = std::less > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); + template< typename OutputIterator, typename Comparator = std::less > + OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator()) + { + return incident_faces(v, dim, out, cmp, true); + } + template< typename OutputIterator, typename Comparator = std::less > + OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); #else - template< typename OutputIterator, typename Comparator > - OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator()) - { - return incident_faces(v, dim, out, cmp, true); - } - template< typename OutputIterator > - OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out) - { - return incident_faces(v, dim, out, std::less(), true); - } - template< typename OutputIterator, typename Comparator > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); - template< typename OutputIterator > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, - std::less = std::less(), bool = false); + template< typename OutputIterator, typename Comparator > + OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator()) + { + return incident_faces(v, dim, out, cmp, true); + } + template< typename OutputIterator > + OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out) + { + return incident_faces(v, dim, out, std::less(), true); + } + template< typename OutputIterator, typename Comparator > + OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); + template< typename OutputIterator > + OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, + std::less = std::less(), bool = false); #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INPUT / OUTPUT - std::istream & read_full_cells(std::istream &, const std::vector &); - std::ostream & write_full_cells(std::ostream &, std::map &) const; + std::istream & read_full_cells(std::istream &, const std::vector &); + std::ostream & write_full_cells(std::ostream &, std::map &) const; }; // end of ``declaration/definition'' of Triangulation_data_structure<...> @@ -624,10 +624,10 @@ OutputIterator Triangulation_data_structure ::incident_full_cells(const Face & f, OutputIterator out) const /* Concept */ { - // CGAL_expensive_precondition_msg(is_full_cell(f.full_cell()), "the facet does not belong to the Triangulation"); - Incident_full_cell_traversal_predicate tp(*this, f); - gather_full_cells(f.full_cell(), tp, out); - return out; + // CGAL_expensive_precondition_msg(is_full_cell(f.full_cell()), "the facet does not belong to the Triangulation"); + Incident_full_cell_traversal_predicate tp(*this, f); + gather_full_cells(f.full_cell(), tp, out); + return out; } template< class Dim, class Vb, class Fcb > @@ -637,10 +637,10 @@ Triangulation_data_structure ::incident_full_cells(Vertex_const_handle v, OutputIterator out) const /* Concept */ { // CGAL_expensive_precondition(is_vertex(v)); - CGAL_precondition(Vertex_handle() != v); - Face f(v->full_cell()); - f.set_index(0, v->full_cell()->index(v)); - return incident_full_cells(f, out); + CGAL_precondition(Vertex_handle() != v); + Face f(v->full_cell()); + f.set_index(0, v->full_cell()->index(v)); + return incident_full_cells(f, out); } template< class Dim, class Vb, class Fcb > @@ -649,10 +649,10 @@ OutputIterator Triangulation_data_structure ::star(const Face & f, OutputIterator out) const /* Concept */ { - // CGAL_precondition_msg(is_full_cell(f.full_cell()), "the facet does not belong to the Triangulation"); - Star_traversal_predicate tp(*this, f); - gather_full_cells(f.full_cell(), tp, out); - return out; + // CGAL_precondition_msg(is_full_cell(f.full_cell()), "the facet does not belong to the Triangulation"); + Star_traversal_predicate tp(*this, f); + gather_full_cells(f.full_cell(), tp, out); + return out; } template< class Dim, class Vb, class Fcb > @@ -660,35 +660,35 @@ template< typename TraversalPredicate, typename OutputIterator > typename Triangulation_data_structure::Facet Triangulation_data_structure ::gather_full_cells(Full_cell_handle start, - TraversalPredicate & tp, - OutputIterator & out) const /* Concept */ + TraversalPredicate & tp, + OutputIterator & out) const /* Concept */ { - std::queue queue; - set_visited(start, true); - queue.push(start); - const int cur_dim = current_dimension(); - Facet ft; - while( ! queue.empty() ) + std::queue queue; + set_visited(start, true); + queue.push(start); + const int cur_dim = current_dimension(); + Facet ft; + while( ! queue.empty() ) + { + Full_cell_handle s = queue.front(); + queue.pop(); + *out = s; + ++out; + for( int i = 0; i <= cur_dim; ++i ) { - Full_cell_handle s = queue.front(); - queue.pop(); - *out = s; - ++out; - for( int i = 0; i <= cur_dim; ++i ) - { - Full_cell_handle n = s->neighbor(i); - if( ! get_visited(n) ) - { - set_visited(n, true); - if( tp(Facet(s, i)) ) - queue.push(n); - else - ft = Facet(s, i); - } - } + Full_cell_handle n = s->neighbor(i); + if( ! get_visited(n) ) + { + set_visited(n, true); + if( tp(Facet(s, i)) ) + queue.push(n); + else + ft = Facet(s, i); + } } - clear_visited_marks(start); - return ft; + } + clear_visited_marks(start); + return ft; } #ifdef CGAL_CFG_NO_CPP0X_DEFAULT_TEMPLATE_ARGUMENTS_FOR_FUNCTION_TEMPLATES @@ -697,9 +697,9 @@ template< typename OutputIterator > OutputIterator Triangulation_data_structure ::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, - std::less cmp, bool upper_faces) + std::less cmp, bool upper_faces) { - return incident_faces >(v, dim, out, cmp, upper_faces); + return incident_faces >(v, dim, out, cmp, upper_faces); } #endif @@ -709,73 +709,73 @@ OutputIterator Triangulation_data_structure ::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp, bool upper_faces) { - CGAL_precondition( 0 < dim ); - if( dim >= current_dimension() ) - return out; - typedef std::vector Simplices; - Simplices simps; - simps.reserve(64); - // gather incident full_cells - std::back_insert_iterator sout(simps); - incident_full_cells(v, sout); - // for storing the handles to the vertices of a full_cell - typedef std::vector Vertices; - typedef std::vector Indices; - Vertices vertices(1 + current_dimension()); - Indices sorted_idx(1 + current_dimension()); - // setup Face comparator and Face_set - typedef internal::Triangulation::Compare_faces_with_common_first_vertex - Upper_face_comparator; - Upper_face_comparator ufc(dim); - typedef std::set Face_set; - Face_set face_set(ufc); - for( typename Simplices::const_iterator s = simps.begin(); s != simps.end(); ++s ) - { - int v_idx(0); // the index of |v| in the sorted full_cell - // get the vertices of the full_cell and sort them - for( int i = 0; i <= current_dimension(); ++i ) - vertices[i] = (*s)->vertex(i); - if( upper_faces ) - { - std::sort(vertices.begin(), vertices.end(), cmp); - while( vertices[v_idx] != v ) - ++v_idx; - } - else - { - while( vertices[v_idx] != v ) - ++v_idx; - if( 0 != v_idx ) - std::swap(vertices[0], vertices[v_idx]); - v_idx = 0; - typename Vertices::iterator vbegin(vertices.begin()); - ++vbegin; - std::sort(vbegin, vertices.end(), cmp); - } - if( v_idx + dim > current_dimension() ) - continue; // |v| is too far to the right - // stores the index of the vertices of s in the same order - // as in |vertices|: - for( int i = 0; i <= current_dimension(); ++i ) - sorted_idx[i] = (*s)->index(vertices[i]); - // init state for enumerating all candidate faces: - internal::Combination_enumerator f_idx(dim, v_idx + 1, current_dimension()); - Face f(*s); - f.set_index(0, v_idx); - while( ! f_idx.end() ) - { - // check if face has already been found - for( int i = 0; i < dim; ++i ) - f.set_index(1 + i, sorted_idx[f_idx[i]]); - face_set.insert(f); - // compute next sorted face (lexicographic enumeration) - ++f_idx; - } - } - typename Face_set::iterator fit = face_set.begin(); - while( fit != face_set.end() ) - *out++ = *fit++; + CGAL_precondition( 0 < dim ); + if( dim >= current_dimension() ) return out; + typedef std::vector Simplices; + Simplices simps; + simps.reserve(64); + // gather incident full_cells + std::back_insert_iterator sout(simps); + incident_full_cells(v, sout); + // for storing the handles to the vertices of a full_cell + typedef std::vector Vertices; + typedef std::vector Indices; + Vertices vertices(1 + current_dimension()); + Indices sorted_idx(1 + current_dimension()); + // setup Face comparator and Face_set + typedef internal::Triangulation::Compare_faces_with_common_first_vertex + Upper_face_comparator; + Upper_face_comparator ufc(dim); + typedef std::set Face_set; + Face_set face_set(ufc); + for( typename Simplices::const_iterator s = simps.begin(); s != simps.end(); ++s ) + { + int v_idx(0); // the index of |v| in the sorted full_cell + // get the vertices of the full_cell and sort them + for( int i = 0; i <= current_dimension(); ++i ) + vertices[i] = (*s)->vertex(i); + if( upper_faces ) + { + std::sort(vertices.begin(), vertices.end(), cmp); + while( vertices[v_idx] != v ) + ++v_idx; + } + else + { + while( vertices[v_idx] != v ) + ++v_idx; + if( 0 != v_idx ) + std::swap(vertices[0], vertices[v_idx]); + v_idx = 0; + typename Vertices::iterator vbegin(vertices.begin()); + ++vbegin; + std::sort(vbegin, vertices.end(), cmp); + } + if( v_idx + dim > current_dimension() ) + continue; // |v| is too far to the right + // stores the index of the vertices of s in the same order + // as in |vertices|: + for( int i = 0; i <= current_dimension(); ++i ) + sorted_idx[i] = (*s)->index(vertices[i]); + // init state for enumerating all candidate faces: + internal::Combination_enumerator f_idx(dim, v_idx + 1, current_dimension()); + Face f(*s); + f.set_index(0, v_idx); + while( ! f_idx.end() ) + { + // check if face has already been found + for( int i = 0; i < dim; ++i ) + f.set_index(1 + i, sorted_idx[f_idx[i]]); + face_set.insert(f); + // compute next sorted face (lexicographic enumeration) + ++f_idx; + } + } + typename Face_set::iterator fit = face_set.begin(); + while( fit != face_set.end() ) + *out++ = *fit++; + return out; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -786,21 +786,21 @@ typename Triangulation_data_structure::Vertex_handle Triangulation_data_structure ::collapse_face(const Face & f) /* Concept */ { - const int fd = f.face_dimension(); - CGAL_precondition( (1 <= fd ) && (fd < current_dimension())); - std::vector simps; - // save the Face's vertices: - Full_cell s; - for( int i = 0; i <= fd; ++i ) - s.set_vertex(i, f.vertex(i)); - // compute the star of f - simps.reserve(64); - std::back_insert_iterator > out(simps); - star(f, out); - Vertex_handle v = insert_in_hole(simps.begin(), simps.end(), Facet(f.full_cell(), f.index(0))); - for( int i = 0; i <= fd; ++i ) - delete_vertex(s.vertex(i)); - return v; + const int fd = f.face_dimension(); + CGAL_precondition( (1 <= fd ) && (fd < current_dimension())); + std::vector simps; + // save the Face's vertices: + Full_cell s; + for( int i = 0; i <= fd; ++i ) + s.set_vertex(i, f.vertex(i)); + // compute the star of f + simps.reserve(64); + std::back_insert_iterator > out(simps); + star(f, out); + Vertex_handle v = insert_in_hole(simps.begin(), simps.end(), Facet(f.full_cell(), f.index(0))); + for( int i = 0; i <= fd; ++i ) + delete_vertex(s.vertex(i)); + return v; } template @@ -808,68 +808,68 @@ void Triangulation_data_structure ::remove_decrease_dimension(Vertex_handle v, Vertex_handle star) /* Concept */ { - CGAL_assertion( current_dimension() >= -1 ); - if( -1 == current_dimension() ) - { - clear(); - return; - } - else if( 0 == current_dimension() ) - { - delete_full_cell(v->full_cell()); - delete_vertex(v); - star->full_cell()->set_neighbor(0, Full_cell_handle()); - set_current_dimension(-1); - return; - } - else if( 1 == current_dimension() ) - { - Full_cell_handle s = v->full_cell(); - int star_index; - if( s->has_vertex(star, star_index) ) - s = s->neighbor(star_index); - // Here, |star| is not a vertex of |s|, so it's the only finite - // full_cell - Full_cell_handle inf1 = s->neighbor(0); - Full_cell_handle inf2 = s->neighbor(1); - Vertex_handle v2 = s->vertex(1 - s->index(v)); - delete_vertex(v); - delete_full_cell(s); - inf1->set_vertex(1, Vertex_handle()); - inf1->set_vertex(1, Vertex_handle()); - inf2->set_neighbor(1, Full_cell_handle()); - inf2->set_neighbor(1, Full_cell_handle()); - associate_vertex_with_full_cell(inf1, 0, star); - associate_vertex_with_full_cell(inf2, 0, v2); - set_neighbors(inf1, 0, inf2, 0); - set_current_dimension(0); - return; - } - typedef std::vector Simplices; - Simplices simps; - incident_full_cells(v, std::back_inserter(simps)); - for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) - { - int v_idx = (*it)->index(v); - if( ! (*it)->has_vertex(star) ) - { - delete_full_cell((*it)->neighbor(v_idx)); - for( int i = 0; i <= current_dimension(); ++i ) - (*it)->vertex(i)->set_full_cell(*it); - } - else - star->set_full_cell(*it); - if( v_idx != current_dimension() ) - { - (*it)->swap_vertices(v_idx, current_dimension()); - if( ( ! (*it)->has_vertex(star) ) || (current_dimension() > 2) ) - (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); - } - (*it)->set_vertex(current_dimension(), Vertex_handle()); - (*it)->set_neighbor(current_dimension(), Full_cell_handle()); - } - set_current_dimension(current_dimension()-1); + CGAL_assertion( current_dimension() >= -1 ); + if( -1 == current_dimension() ) + { + clear(); + return; + } + else if( 0 == current_dimension() ) + { + delete_full_cell(v->full_cell()); delete_vertex(v); + star->full_cell()->set_neighbor(0, Full_cell_handle()); + set_current_dimension(-1); + return; + } + else if( 1 == current_dimension() ) + { + Full_cell_handle s = v->full_cell(); + int star_index; + if( s->has_vertex(star, star_index) ) + s = s->neighbor(star_index); + // Here, |star| is not a vertex of |s|, so it's the only finite + // full_cell + Full_cell_handle inf1 = s->neighbor(0); + Full_cell_handle inf2 = s->neighbor(1); + Vertex_handle v2 = s->vertex(1 - s->index(v)); + delete_vertex(v); + delete_full_cell(s); + inf1->set_vertex(1, Vertex_handle()); + inf1->set_vertex(1, Vertex_handle()); + inf2->set_neighbor(1, Full_cell_handle()); + inf2->set_neighbor(1, Full_cell_handle()); + associate_vertex_with_full_cell(inf1, 0, star); + associate_vertex_with_full_cell(inf2, 0, v2); + set_neighbors(inf1, 0, inf2, 0); + set_current_dimension(0); + return; + } + typedef std::vector Simplices; + Simplices simps; + incident_full_cells(v, std::back_inserter(simps)); + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + { + int v_idx = (*it)->index(v); + if( ! (*it)->has_vertex(star) ) + { + delete_full_cell((*it)->neighbor(v_idx)); + for( int i = 0; i <= current_dimension(); ++i ) + (*it)->vertex(i)->set_full_cell(*it); + } + else + star->set_full_cell(*it); + if( v_idx != current_dimension() ) + { + (*it)->swap_vertices(v_idx, current_dimension()); + if( ( ! (*it)->has_vertex(star) ) || (current_dimension() > 2) ) + (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); + } + (*it)->set_vertex(current_dimension(), Vertex_handle()); + (*it)->set_neighbor(current_dimension(), Full_cell_handle()); + } + set_current_dimension(current_dimension()-1); + delete_vertex(v); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -880,31 +880,31 @@ typename Triangulation_data_structure::Vertex_handle Triangulation_data_structure ::insert_in_full_cell(Full_cell_handle s) /* Concept */ { - CGAL_precondition(0 < current_dimension()); - CGAL_precondition(Full_cell_handle() != s); - // CGAL_expensive_precondition(is_full_cell(s)); + CGAL_precondition(0 < current_dimension()); + CGAL_precondition(Full_cell_handle() != s); + // CGAL_expensive_precondition(is_full_cell(s)); - const int cur_dim = current_dimension(); - Vertex_handle v = new_vertex(); - // the full_cell 'fc' is just used to store the handle to all the new full_cells. - Full_cell fc(maximal_dimension()); - for( int i = 1; i <= cur_dim; ++i ) + const int cur_dim = current_dimension(); + Vertex_handle v = new_vertex(); + // the full_cell 'fc' is just used to store the handle to all the new full_cells. + Full_cell fc(maximal_dimension()); + for( int i = 1; i <= cur_dim; ++i ) + { + Full_cell_handle new_s = new_full_cell(s); + fc.set_neighbor(i, new_s); + associate_vertex_with_full_cell(new_s, i, v); + s->vertex(i-1)->set_full_cell(new_s); + set_neighbors(new_s, i, neighbor(s, i), mirror_index(s, i)); + } + fc.set_neighbor(0, s); + associate_vertex_with_full_cell(s, 0, v); + for( int i = 0; i <= cur_dim; ++i ) + for( int j = 0; j <= cur_dim; ++j ) { - Full_cell_handle new_s = new_full_cell(s); - fc.set_neighbor(i, new_s); - associate_vertex_with_full_cell(new_s, i, v); - s->vertex(i-1)->set_full_cell(new_s); - set_neighbors(new_s, i, neighbor(s, i), mirror_index(s, i)); + if( j == i ) continue; + set_neighbors(fc.neighbor(i), j, fc.neighbor(j), i); } - fc.set_neighbor(0, s); - associate_vertex_with_full_cell(s, 0, v); - for( int i = 0; i <= cur_dim; ++i ) - for( int j = 0; j <= cur_dim; ++j ) - { - if( j == i ) continue; - set_neighbors(fc.neighbor(i), j, fc.neighbor(j), i); - } - return v; + return v; } template @@ -912,23 +912,23 @@ typename Triangulation_data_structure::Vertex_handle Triangulation_data_structure ::insert_in_face(const Face & f) /* Concept */ { - std::vector simps; - simps.reserve(64); - std::back_insert_iterator > out(simps); - incident_full_cells(f, out); - return insert_in_hole(simps.begin(), simps.end(), Facet(f.full_cell(), f.index(0))); + std::vector simps; + simps.reserve(64); + std::back_insert_iterator > out(simps); + incident_full_cells(f, out); + return insert_in_hole(simps.begin(), simps.end(), Facet(f.full_cell(), f.index(0))); } template typename Triangulation_data_structure::Vertex_handle Triangulation_data_structure ::insert_in_facet(const Facet & ft) /* Concept */ { - Full_cell_handle s[2]; - s[0] = full_cell(ft); - int i = index_of_covertex(ft); - s[1] = s[0]->neighbor(i); - i = ( i + 1 ) % current_dimension(); - return insert_in_hole(s, s+2, Facet(s[0], i)); + Full_cell_handle s[2]; + s[0] = full_cell(ft); + int i = index_of_covertex(ft); + s[1] = s[0]->neighbor(i); + i = ( i + 1 ) % current_dimension(); + return insert_in_hole(s, s+2, Facet(s[0], i)); } template @@ -936,62 +936,62 @@ template < typename OutputIterator > typename Triangulation_data_structure::Full_cell_handle Triangulation_data_structure ::insert_in_tagged_hole(Vertex_handle v, Facet f, - OutputIterator new_full_cells) + OutputIterator new_full_cells) { - CGAL_assertion_msg(is_boundary_facet(f), "starting facet should be on the hole boundary"); + CGAL_assertion_msg(is_boundary_facet(f), "starting facet should be on the hole boundary"); - const int cur_dim = current_dimension(); + const int cur_dim = current_dimension(); - Full_cell_handle old_s = full_cell(f); - Full_cell_handle new_s = new_full_cell(); - const int facet_index = index_of_covertex(f); + Full_cell_handle old_s = full_cell(f); + Full_cell_handle new_s = new_full_cell(); + const int facet_index = index_of_covertex(f); - int i(0); - for( ; i < facet_index; ++i ) - associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); - ++i; // skip facet_index - for( ; i <= cur_dim; ++i ) - associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); - associate_vertex_with_full_cell(new_s, facet_index, v); - set_neighbors( new_s, - facet_index, - neighbor(old_s, facet_index), - mirror_index(old_s, facet_index)); + int i(0); + for( ; i < facet_index; ++i ) + associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); + ++i; // skip facet_index + for( ; i <= cur_dim; ++i ) + associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); + associate_vertex_with_full_cell(new_s, facet_index, v); + set_neighbors( new_s, + facet_index, + neighbor(old_s, facet_index), + mirror_index(old_s, facet_index)); - // add the new full_cell to the list of new full_cells - *new_full_cells++ = new_s; + // add the new full_cell to the list of new full_cells + *new_full_cells++ = new_s; + + // check all of |Facet f|'s neighbors + for( i = 0; i <= cur_dim; ++i ) + { + if( facet_index == i ) + continue; + // we define a |Rotor| because it makes it easy to rotate around + // in a self contained fashion. The corresponding potential + // boundary facet is Facet(full_cell(rot), index_of_covertex(rot)) + Rotor rot(old_s, i, facet_index); + // |rot| on line above, stands for Candidate Facet + while( ! is_boundary_facet(rot) ) + rot = rotate_rotor(rot); - // check all of |Facet f|'s neighbors - for( i = 0; i <= cur_dim; ++i ) - { - if( facet_index == i ) - continue; - // we define a |Rotor| because it makes it easy to rotate around - // in a self contained fashion. The corresponding potential - // boundary facet is Facet(full_cell(rot), index_of_covertex(rot)) - Rotor rot(old_s, i, facet_index); - // |rot| on line above, stands for Candidate Facet - while( ! is_boundary_facet(rot) ) - rot = rotate_rotor(rot); + // we did find the |i|-th neighbor of Facet(old_s, facet_index)... + // has it already been extruded to center point |v| ? + Full_cell_handle outside = neighbor(full_cell(rot), index_of_covertex(rot)); + Full_cell_handle inside = full_cell(rot); + Vertex_handle m = inside->mirror_vertex(index_of_covertex(rot), current_dimension()); + int index = outside->index(m); + Full_cell_handle new_neighbor = outside->neighbor(index); - // we did find the |i|-th neighbor of Facet(old_s, facet_index)... - // has it already been extruded to center point |v| ? - Full_cell_handle outside = neighbor(full_cell(rot), index_of_covertex(rot)); - Full_cell_handle inside = full_cell(rot); - Vertex_handle m = inside->mirror_vertex(index_of_covertex(rot), current_dimension()); - int index = outside->index(m); - Full_cell_handle new_neighbor = outside->neighbor(index); - - if( new_neighbor == inside ) - { // not already extruded... we do it recursively - new_neighbor = insert_in_tagged_hole( v, - Facet(full_cell(rot), index_of_covertex(rot)), - new_full_cells); - } - // now the new neighboring full_cell exists, we link both - set_neighbors(new_s, i, new_neighbor, index_of_second_covertex(rot)); + if( new_neighbor == inside ) + { // not already extruded... we do it recursively + new_neighbor = insert_in_tagged_hole( + v, Facet(full_cell(rot), index_of_covertex(rot)), + new_full_cells); } - return new_s; + // now the new neighboring full_cell exists, we link both + set_neighbors(new_s, i, new_neighbor, index_of_second_covertex(rot)); + } + return new_s; } template< class Dim, class Vb, class Fcb > @@ -999,18 +999,18 @@ template< typename Forward_iterator, typename OutputIterator > typename Triangulation_data_structure::Vertex_handle Triangulation_data_structure ::insert_in_hole(Forward_iterator start, Forward_iterator end, Facet f, - OutputIterator out) /* Concept */ + OutputIterator out) /* Concept */ { - CGAL_expensive_precondition( - ( std::distance(start, end) == 1 ) - || ( current_dimension() > 1 ) ); - Forward_iterator sit = start; - while( end != sit ) - set_visited(*sit++, true); - Vertex_handle v = new_vertex(); - insert_in_tagged_hole(v, f, out); - delete_full_cells(start, end); - return v; + CGAL_expensive_precondition( + ( std::distance(start, end) == 1 ) + || ( current_dimension() > 1 ) ); + Forward_iterator sit = start; + while( end != sit ) + set_visited(*sit++, true); + Vertex_handle v = new_vertex(); + insert_in_tagged_hole(v, f, out); + delete_full_cells(start, end); + return v; } template< class Dim, class Vb, class Fcb > @@ -1019,8 +1019,8 @@ typename Triangulation_data_structure::Vertex_handle Triangulation_data_structure ::insert_in_hole(Forward_iterator start, Forward_iterator end, Facet f) /* Concept */ { - Emptyset_iterator out; - return insert_in_hole(start, end, f, out); + Emptyset_iterator out; + return insert_in_hole(start, end, f, out); } template @@ -1028,104 +1028,104 @@ void Triangulation_data_structure ::clear_visited_marks(Full_cell_handle start) const // NOT DOCUMENTED { - CGAL_precondition(start != Full_cell_handle()); + CGAL_precondition(start != Full_cell_handle()); - std::queue queue; - set_visited(start, false); - queue.push(start); - const int cur_dim = current_dimension(); - while( ! queue.empty() ) + std::queue queue; + set_visited(start, false); + queue.push(start); + const int cur_dim = current_dimension(); + while( ! queue.empty() ) + { + Full_cell_handle s = queue.front(); + queue.pop(); + for( int i = 0; i <= cur_dim; ++i ) { - Full_cell_handle s = queue.front(); - queue.pop(); - for( int i = 0; i <= cur_dim; ++i ) - { - if( get_visited(s->neighbor(i)) ) - { - set_visited(s->neighbor(i), false); - queue.push(s->neighbor(i)); - } - } + if( get_visited(s->neighbor(i)) ) + { + set_visited(s->neighbor(i), false); + queue.push(s->neighbor(i)); + } } + } } template void Triangulation_data_structure ::do_insert_increase_dimension(const Vertex_handle x, const Vertex_handle star) { - Full_cell_handle start = full_cells_begin(); - Full_cell_handle swap_me; - const int cur_dim = current_dimension(); + Full_cell_handle start = full_cells_begin(); + Full_cell_handle swap_me; + const int cur_dim = current_dimension(); + for( Full_cell_iterator S = full_cells_begin(); S != full_cells_end(); ++S ) + { + if( Vertex_handle() != S->vertex(cur_dim) ) + continue; + set_visited(S, true); + // extends full_cell |S| to include the new vertex as the + // current_dimension()-th vertex + associate_vertex_with_full_cell(S, cur_dim, x); + if( ! S->has_vertex(star) ) + { // S is bounded, we create its unbounded "twin" full_cell + Full_cell_handle S_new = new_full_cell(); + set_neighbors(S, cur_dim, S_new, 0); + associate_vertex_with_full_cell(S_new, 0, star); + // here, we could be clever so as to get consistent orientation + for( int k = 1; k <= cur_dim; ++k ) + associate_vertex_with_full_cell(S_new, k, vertex(S, k - 1)); + } + else if( cur_dim == 2 ) + { // if cur. dim. is 2, we must take care of the 'rightmost' infinite vertex. + if( S->mirror_index(S->index(star)) == 0 ) + swap_me = S; + } + } + // now we setup the neighbors + set_visited(start, false); + std::queue queue; + queue.push(start); + while( ! queue.empty() ) + { + Full_cell_handle S = queue.front(); + queue.pop(); + // here, the first visit above ensured that all neighbors exist now. + // Now we need to connect them with adjacency relation + int star_index; + if( S->has_vertex(star, star_index) ) + { + set_neighbors( S, cur_dim, neighbor(neighbor(S, star_index), cur_dim), + // this is tricky :-) : + mirror_index(S, star_index) + 1); + } + else + { + Full_cell_handle S_new = neighbor(S, cur_dim); + for( int k = 0 ; k < cur_dim ; ++k ) + { + Full_cell_handle S_opp = neighbor(S, k); + if( ! S_opp->has_vertex(star) ) + set_neighbors(S_new, k + 1, neighbor(S_opp, cur_dim), mirror_index(S, k) + 1); + // neighbor of S_new opposite to v is S_new' + // the vertex opposite to v remains the same but ... + // remember the shifting of the vertices one step to the right + } + } + for( int k = 0 ; k < cur_dim ; ++k ) + if( get_visited(neighbor(S, k)) ) + { + set_visited(neighbor(S, k), false); + queue.push(neighbor(S, k)); + } + } + if( ( ( cur_dim % 2 ) == 0 ) && ( cur_dim > 1 ) ) + { for( Full_cell_iterator S = full_cells_begin(); S != full_cells_end(); ++S ) { - if( Vertex_handle() != S->vertex(cur_dim) ) - continue; - set_visited(S, true); - // extends full_cell |S| to include the new vertex as the - // current_dimension()-th vertex - associate_vertex_with_full_cell(S, cur_dim, x); - if( ! S->has_vertex(star) ) - { // S is bounded, we create its unbounded "twin" full_cell - Full_cell_handle S_new = new_full_cell(); - set_neighbors(S, cur_dim, S_new, 0); - associate_vertex_with_full_cell(S_new, 0, star); - // here, we could be clever so as to get consistent orientation - for( int k = 1; k <= cur_dim; ++k ) - associate_vertex_with_full_cell(S_new, k, vertex(S, k - 1)); - } - else if( cur_dim == 2 ) - { // if cur. dim. is 2, we must take care of the 'rightmost' infinite vertex. - if( S->mirror_index(S->index(star)) == 0 ) - swap_me = S; - } + if( x != S->vertex(cur_dim) ) + S->swap_vertices(cur_dim - 1, cur_dim); } - // now we setup the neighbors - set_visited(start, false); - std::queue queue; - queue.push(start); - while( ! queue.empty() ) - { - Full_cell_handle S = queue.front(); - queue.pop(); - // here, the first visit above ensured that all neighbors exist now. - // Now we need to connect them with adjacency relation - int star_index; - if( S->has_vertex(star, star_index) ) - { - set_neighbors( S, cur_dim, neighbor(neighbor(S, star_index), cur_dim), - // this is tricky :-) : - mirror_index(S, star_index) + 1); - } - else - { - Full_cell_handle S_new = neighbor(S, cur_dim); - for( int k = 0 ; k < cur_dim ; ++k ) - { - Full_cell_handle S_opp = neighbor(S, k); - if( ! S_opp->has_vertex(star) ) - set_neighbors(S_new, k + 1, neighbor(S_opp, cur_dim), mirror_index(S, k) + 1); - // neighbor of S_new opposite to v is S_new' - // the vertex opposite to v remains the same but ... - // remember the shifting of the vertices one step to the right - } - } - for( int k = 0 ; k < cur_dim ; ++k ) - if( get_visited(neighbor(S, k)) ) - { - set_visited(neighbor(S, k), false); - queue.push(neighbor(S, k)); - } - } - if( ( ( cur_dim % 2 ) == 0 ) && ( cur_dim > 1 ) ) - { - for( Full_cell_iterator S = full_cells_begin(); S != full_cells_end(); ++S ) - { - if( x != S->vertex(cur_dim) ) - S->swap_vertices(cur_dim - 1, cur_dim); - } - } - if( Full_cell_handle() != swap_me ) - swap_me->swap_vertices(1, 2); + } + if( Full_cell_handle() != swap_me ) + swap_me->swap_vertices(1, 2); } template @@ -1133,41 +1133,41 @@ typename Triangulation_data_structure::Vertex_handle Triangulation_data_structure ::insert_increase_dimension(Vertex_handle star) /* Concept */ { - const int prev_cur_dim = current_dimension(); - CGAL_precondition(prev_cur_dim < maximal_dimension()); - if( -2 != current_dimension() ) - { - CGAL_precondition( Vertex_handle() != star ); - CGAL_expensive_precondition(is_vertex(star)); - } + const int prev_cur_dim = current_dimension(); + CGAL_precondition(prev_cur_dim < maximal_dimension()); + if( -2 != current_dimension() ) + { + CGAL_precondition( Vertex_handle() != star ); + CGAL_expensive_precondition(is_vertex(star)); + } - set_current_dimension(prev_cur_dim + 1); - Vertex_handle v = new_vertex(); - switch( prev_cur_dim ) - { - case -2: - { // insertion of the first vertex - // ( geometrically : infinite vertex ) - Full_cell_handle s = new_full_cell(); - associate_vertex_with_full_cell(s, 0, v); - break; - } - case -1: - { // insertion of the second vertex - // ( geometrically : first finite vertex ) - //we create a triangulation of the 0-sphere, with - // vertices |star| and |v| - Full_cell_handle infinite_full_cell = star->full_cell(); - Full_cell_handle finite_full_cell = new_full_cell(); - associate_vertex_with_full_cell(finite_full_cell, 0, v); - set_neighbors(infinite_full_cell, 0, finite_full_cell, 0); - break; - } - default: - do_insert_increase_dimension(v, star); - break; + set_current_dimension(prev_cur_dim + 1); + Vertex_handle v = new_vertex(); + switch( prev_cur_dim ) + { + case -2: + { // insertion of the first vertex + // ( geometrically : infinite vertex ) + Full_cell_handle s = new_full_cell(); + associate_vertex_with_full_cell(s, 0, v); + break; } - return v; + case -1: + { // insertion of the second vertex + // ( geometrically : first finite vertex ) + //we create a triangulation of the 0-sphere, with + // vertices |star| and |v| + Full_cell_handle infinite_full_cell = star->full_cell(); + Full_cell_handle finite_full_cell = new_full_cell(); + associate_vertex_with_full_cell(finite_full_cell, 0, v); + set_neighbors(infinite_full_cell, 0, finite_full_cell, 0); + break; + } + default: + do_insert_increase_dimension(v, star); + break; + } + return v; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1177,85 +1177,85 @@ template bool Triangulation_data_structure ::is_valid(bool verbose, int /* level */) const /* Concept */ { - Full_cell_const_handle s, t; - Vertex_const_handle v; - int i, j, k; + Full_cell_const_handle s, t; + Vertex_const_handle v; + int i, j, k; - if( current_dimension() == -2 ) + if( current_dimension() == -2 ) + { + if( ! vertices_.empty() || ! full_cells_.empty() ) { - if( ! vertices_.empty() || ! full_cells_.empty() ) - { - if( verbose ) CGAL_warning_msg(false, "current dimension is -2 but there are vertices or full_cells"); - return false; - } + if( verbose ) CGAL_warning_msg(false, "current dimension is -2 but there are vertices or full_cells"); + return false; } + } - if( current_dimension() == -1 ) + if( current_dimension() == -1 ) + { + if ( (number_of_vertices() != 1) || (number_of_full_cells() != 1) ) { - if ( (number_of_vertices() != 1) || (number_of_full_cells() != 1) ) - { - if( verbose ) CGAL_warning_msg(false, "current dimension is -1 but there isn't one vertex and one full_cell"); - return false; - } + if( verbose ) CGAL_warning_msg(false, "current dimension is -1 but there isn't one vertex and one full_cell"); + return false; } + } - for( v = vertices_begin(); v != vertices_end(); ++v ) - { - if( ! v->is_valid(verbose) ) - return false; - } - - // FUTURE: for each vertex v, gather incident full_cells. then, check that - // any full_cell containing v is among those gathered full_cells... + for( v = vertices_begin(); v != vertices_end(); ++v ) + { + if( ! v->is_valid(verbose) ) + return false; + } + + // FUTURE: for each vertex v, gather incident full_cells. then, check that + // any full_cell containing v is among those gathered full_cells... - if( current_dimension() < 0 ) - return true; - - for( s = full_cells_begin(); s != full_cells_end(); ++s ) - { - if( ! s->is_valid(verbose) ) - return false; - // check that the full cell has no duplicate vertices - for( i = 0; i <= current_dimension(); ++i ) - for( j = i + 1; j <= current_dimension(); ++j ) - if( vertex(s,i) == vertex(s,j) ) - { - CGAL_warning_msg(false, "a full_cell has two equal vertices"); - return false; - } - } - - for( s = full_cells_begin(); s != full_cells_end(); ++s ) - { - for( i = 0; i <= current_dimension(); ++i ) - if( (t = neighbor(s,i)) != Full_cell_const_handle() ) - { - int l = mirror_index(s,i); - if( s != neighbor(t,l) || i != mirror_index(t,l) ) - { - if( verbose ) CGAL_warning_msg(false, "neighbor relation is not symmetric"); - return false; - } - for( j = 0; j <= current_dimension(); ++j ) - if( j != i ) - { - // j must also occur as a vertex of t - for( k = 0; k <= current_dimension() && ( vertex(s,j) != vertex(t,k) || k == l); ++k ) - ; - if( k > current_dimension() ) - { - if( verbose ) CGAL_warning_msg(false, "too few shared vertices between neighbors full_cells."); - return false; - } - } - } - else - { - if( verbose ) CGAL_warning_msg(false, "full_cell has a NULL neighbor"); - return false; - } - } + if( current_dimension() < 0 ) return true; + + for( s = full_cells_begin(); s != full_cells_end(); ++s ) + { + if( ! s->is_valid(verbose) ) + return false; + // check that the full cell has no duplicate vertices + for( i = 0; i <= current_dimension(); ++i ) + for( j = i + 1; j <= current_dimension(); ++j ) + if( vertex(s,i) == vertex(s,j) ) + { + CGAL_warning_msg(false, "a full_cell has two equal vertices"); + return false; + } + } + + for( s = full_cells_begin(); s != full_cells_end(); ++s ) + { + for( i = 0; i <= current_dimension(); ++i ) + if( (t = neighbor(s,i)) != Full_cell_const_handle() ) + { + int l = mirror_index(s,i); + if( s != neighbor(t,l) || i != mirror_index(t,l) ) + { + if( verbose ) CGAL_warning_msg(false, "neighbor relation is not symmetric"); + return false; + } + for( j = 0; j <= current_dimension(); ++j ) + if( j != i ) + { + // j must also occur as a vertex of t + for( k = 0; k <= current_dimension() && ( vertex(s,j) != vertex(t,k) || k == l); ++k ) + ; + if( k > current_dimension() ) + { + if( verbose ) CGAL_warning_msg(false, "too few shared vertices between neighbors full_cells."); + return false; + } + } + } + else + { + if( verbose ) CGAL_warning_msg(false, "full_cell has a NULL neighbor"); + return false; + } + } + return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1267,45 +1267,45 @@ template void Triangulation_data_structure ::write_graph(OutStream & os) { - std::vector > edges; - os << number_of_vertices() + 1; // add the vertex at infinity - int count(1); - for( Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit ) - vit->idx_ = count++; - edges.resize(number_of_vertices()+1); - for( Full_cell_iterator sit = full_cells_begin(); sit != full_cells_end(); ++sit ) + std::vector > edges; + os << number_of_vertices() + 1; // add the vertex at infinity + int count(1); + for( Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit ) + vit->idx_ = count++; + edges.resize(number_of_vertices()+1); + for( Full_cell_iterator sit = full_cells_begin(); sit != full_cells_end(); ++sit ) + { + int v1 = 0; + while( v1 < current_dimension() ) { - int v1 = 0; - while( v1 < current_dimension() ) - { - int v2 = v1 + 1; - while( v2 <= current_dimension() ) - { - int i1, i2; - if( Vertex_handle() != sit-> vertex(v1) ) - i1 = sit->vertex(v1)->idx_; - else - i1 = 0; - if( Vertex_handle() != sit-> vertex(v2) ) - i2 = sit->vertex(v2)->idx_; - else - i2 = 0; - edges[i1].insert(i2); - edges[i2].insert(i1); - ++v2; - } - ++v1; - } + int v2 = v1 + 1; + while( v2 <= current_dimension() ) + { + int i1, i2; + if( Vertex_handle() != sit-> vertex(v1) ) + i1 = sit->vertex(v1)->idx_; + else + i1 = 0; + if( Vertex_handle() != sit-> vertex(v2) ) + i2 = sit->vertex(v2)->idx_; + else + i2 = 0; + edges[i1].insert(i2); + edges[i2].insert(i1); + ++v2; + } + ++v1; } - for( int i = 0; i < edges.size(); ++i ) + } + for( int i = 0; i < edges.size(); ++i ) + { + os << std::endl << edges[i].size(); + for( std::set::const_iterator nit = edges[i].begin(); + nit != edges[i].end(); ++nit ) { - os << std::endl << edges[i].size(); - for( std::set::const_iterator nit = edges[i].begin(); - nit != edges[i].end(); ++nit ) - { - os << ' ' << (*nit); - } + os << ' ' << (*nit); } + } } // NOT DOCUMENTED... @@ -1314,76 +1314,76 @@ std::istream & Triangulation_data_structure ::read_full_cells(std::istream & is, const std::vector & vertices) { - size_t m; // number of full_cells - int index; - const int cd = current_dimension(); - if( is_ascii(is) ) - is >> m; - else - read(is, m, io_Read_write()); + size_t m; // number of full_cells + int index; + const int cd = current_dimension(); + if( is_ascii(is) ) + is >> m; + else + read(is, m, io_Read_write()); - std::vector full_cells; - full_cells.reserve(m); - // read the vertices of each full_cell - size_t i = 0; + std::vector full_cells; + full_cells.reserve(m); + // read the vertices of each full_cell + size_t i = 0; + while( i < m ) + { + Full_cell_handle s = new_full_cell(); + full_cells.push_back(s); + for( int j = 0; j <= cd; ++j ) + { + if( is_ascii(is) ) + is >> index; + else + read(is, index); + s->set_vertex(j, vertices[index]); + } + // read other non-combinatorial information for the full_cells + is >> (*s); + ++i; + } + + // read the neighbors of each full_cell + i = 0; + if( is_ascii(is) ) while( i < m ) + { + for( int j = 0; j <= cd; ++j ) { - Full_cell_handle s = new_full_cell(); - full_cells.push_back(s); - for( int j = 0; j <= cd; ++j ) - { - if( is_ascii(is) ) - is >> index; - else - read(is, index); - s->set_vertex(j, vertices[index]); - } - // read other non-combinatorial information for the full_cells - is >> (*s); - ++i; + is >> index; + full_cells[i]->set_neighbor(j, full_cells[index]); } + ++i; + } + else + while( i < m ) + { + for( int j = 0; j <= cd; ++j ) + { + read(is, index); + full_cells[i]->set_neighbor(j, full_cells[index]); + } + ++i; + } - // read the neighbors of each full_cell - i = 0; - if( is_ascii(is) ) - while( i < m ) + // compute the mirror indices + for( i = 0; i < m; ++i ) + { + Full_cell_handle s = full_cells[i]; + for( int j = 0; j <= cd; ++j ) { - for( int j = 0; j <= cd; ++j ) - { - is >> index; - full_cells[i]->set_neighbor(j, full_cells[index]); - } - ++i; + if( -1 != s->mirror_index(j) ) + continue; + Full_cell_handle n = s->neighbor(j); + int k = 0; + Full_cell_handle nn = n->neighbor(k); + while( s != nn ) + nn = n->neighbor(++k); + s->set_mirror_index(j,k); + n->set_mirror_index(k,j); } - else - while( i < m ) - { - for( int j = 0; j <= cd; ++j ) - { - read(is, index); - full_cells[i]->set_neighbor(j, full_cells[index]); - } - ++i; - } - - // compute the mirror indices - for( i = 0; i < m; ++i ) - { - Full_cell_handle s = full_cells[i]; - for( int j = 0; j <= cd; ++j ) - { - if( -1 != s->mirror_index(j) ) - continue; - Full_cell_handle n = s->neighbor(j); - int k = 0; - Full_cell_handle nn = n->neighbor(k); - while( s != nn ) - nn = n->neighbor(++k); - s->set_mirror_index(j,k); - n->set_mirror_index(k,j); - } - } - return is; + } + return is; } // NOT DOCUMENTED... @@ -1392,52 +1392,52 @@ std::ostream & Triangulation_data_structure ::write_full_cells(std::ostream & os, std::map & index_of_vertex) const { - std::map index_of_full_cell; + std::map index_of_full_cell; - size_t m = number_of_full_cells(); + size_t m = number_of_full_cells(); + if( is_ascii(os) ) + os << std::endl << m; + else + write(os, m, io_Read_write()); + + const int cur_dim = current_dimension(); + // write the vertex indices of each full_cell + int i = 0; + for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it ) + { + index_of_full_cell[it] = i++; if( is_ascii(os) ) - os << std::endl << m; - else - write(os, m, io_Read_write()); + os << std::endl; + for( int j = 0; j <= cur_dim; ++j ) + { + if( is_ascii(os) ) + os << ' ' << index_of_vertex[it->vertex(j)]; + else + write(os, index_of_vertex[it->vertex(j)]); + } + // write other non-combinatorial information for the full_cells + os << (*it); + } - const int cur_dim = current_dimension(); - // write the vertex indices of each full_cell - int i = 0; + CGAL_assertion( i == m ); + + // write the neighbors of each full_cell + if( is_ascii(os) ) for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it ) { - index_of_full_cell[it] = i++; - if( is_ascii(os) ) - os << std::endl; - for( int j = 0; j <= cur_dim; ++j ) - { - if( is_ascii(os) ) - os << ' ' << index_of_vertex[it->vertex(j)]; - else - write(os, index_of_vertex[it->vertex(j)]); - } - // write other non-combinatorial information for the full_cells - os << (*it); + os << std::endl; + for( int j = 0; j <= cur_dim; ++j ) + os << ' ' << index_of_full_cell[it->neighbor(j)]; + } + else + for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it ) + { + for( int j = 0; j <= cur_dim; ++j ) + write(os, index_of_full_cell[it->neighbor(j)]); } - CGAL_assertion( i == m ); - - // write the neighbors of each full_cell - if( is_ascii(os) ) - for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it ) - { - os << std::endl; - for( int j = 0; j <= cur_dim; ++j ) - os << ' ' << index_of_full_cell[it->neighbor(j)]; - } - else - for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it ) - { - for( int j = 0; j <= cur_dim; ++j ) - write(os, index_of_full_cell[it->neighbor(j)]); - } - - return os; + return os; } // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = @@ -1456,42 +1456,42 @@ operator>>(std::istream & is, Triangulation_data_structure & tr) // of vertices, plus the non combinatorial information on each full_cell // - the neighbors of each full_cell by their index in the preceding list { - typedef Triangulation_data_structure TDS; - typedef typename TDS::Vertex_handle Vertex_handle; + typedef Triangulation_data_structure TDS; + typedef typename TDS::Vertex_handle Vertex_handle; - // read current dimension and number of vertices - size_t n; - int cd; - if( is_ascii(is) ) - is >> cd >> n; - else - { - read(is, cd); - read(is, n, io_Read_write()); - } + // read current dimension and number of vertices + size_t n; + int cd; + if( is_ascii(is) ) + is >> cd >> n; + else + { + read(is, cd); + read(is, n, io_Read_write()); + } - CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation_data_structure has too high dimension"); + CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation_data_structure has too high dimension"); - tr.clear(); - tr.set_current_dimension(cd); + tr.clear(); + tr.set_current_dimension(cd); - if( n == 0 ) - return is; + if( n == 0 ) + return is; - std::vector vertices; - vertices.resize(n); + std::vector vertices; + vertices.resize(n); - // read the vertices: - size_t i(0); - while( i < n ) - { - vertices[i] = tr.new_vertex(); - is >> (*vertices[i]); // read a vertex - ++i; - } + // read the vertices: + size_t i(0); + while( i < n ) + { + vertices[i] = tr.new_vertex(); + is >> (*vertices[i]); // read a vertex + ++i; + } - // now, read the combinatorial information - return tr.read_full_cells(is, vertices); + // now, read the combinatorial information + return tr.read_full_cells(is, vertices); } template @@ -1506,35 +1506,35 @@ operator<<(std::ostream & os, const Triangulation_data_structure // of vertices, plus the non combinatorial information on each full_cell // - the neighbors of each full_cell by their index in the preceding list { - typedef Triangulation_data_structure TDS; - typedef typename TDS::Vertex_const_handle Vertex_handle; - typedef typename TDS::Vertex_const_iterator Vertex_iterator; + typedef Triangulation_data_structure TDS; + typedef typename TDS::Vertex_const_handle Vertex_handle; + typedef typename TDS::Vertex_const_iterator Vertex_iterator; - // outputs dimension and number of vertices - size_t n = tr.number_of_vertices(); - if( is_ascii(os) ) - os << tr.current_dimension() << std::endl << n; - else - { - write(os, tr.current_dimension()); - write(os, n, io_Read_write()); - } + // outputs dimension and number of vertices + size_t n = tr.number_of_vertices(); + if( is_ascii(os) ) + os << tr.current_dimension() << std::endl << n; + else + { + write(os, tr.current_dimension()); + write(os, n, io_Read_write()); + } - if( n == 0 ) - return os; + if( n == 0 ) + return os; - // write the vertices - std::map index_of_vertex; - int i = 0; - for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it, ++i ) - { - os << *it << std::endl; // write the vertex - index_of_vertex[it] = i; - } - CGAL_assertion( i == n ); + // write the vertices + std::map index_of_vertex; + int i = 0; + for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it, ++i ) + { + os << *it << std::endl; // write the vertex + index_of_vertex[it] = i; + } + CGAL_assertion( i == n ); - // output the combinatorial information - return tr.write_full_cells(os, index_of_vertex); + // output the combinatorial information + return tr.write_full_cells(os, index_of_vertex); } } //namespace CGAL From 7d0d7293f067a842c090679badfe917a591efe28 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Jun 2014 19:27:52 +0200 Subject: [PATCH 038/487] Derecursify insert_in_tagged_hole No stack overflow anymore. --- .../CGAL/Triangulation_data_structure.h | 149 +++++++++++++----- 1 file changed, 106 insertions(+), 43 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 0b0674a263c..90eedfc554b 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -387,6 +387,30 @@ public: private: + // Used by insert_in_tagged_hole + struct IITH_task + { + IITH_task( + Facet boundary_facet_, + int index_of_inside_cell_in_outside_cell_, + Full_cell_handle future_neighbor_ = Full_cell_handle(), + int new_cell_index_in_future_neighbor_ = -1, + int index_of_future_neighbor_in_new_cell_ = -1) + : boundary_facet(boundary_facet_), + index_of_inside_cell_in_outside_cell(index_of_inside_cell_in_outside_cell_), + future_neighbor(future_neighbor_), + new_cell_index_in_future_neighbor(new_cell_index_in_future_neighbor_), + index_of_future_neighbor_in_new_cell(index_of_future_neighbor_in_new_cell_) + {} + + // "new_cell" is the cell about to be created + Facet boundary_facet; + int index_of_inside_cell_in_outside_cell; + Full_cell_handle future_neighbor; + int new_cell_index_in_future_neighbor; + int index_of_future_neighbor_in_new_cell; + }; + // NOT DOCUMENTED void clear_visited_marks(Full_cell_handle) const; @@ -941,56 +965,95 @@ Triangulation_data_structure CGAL_assertion_msg(is_boundary_facet(f), "starting facet should be on the hole boundary"); const int cur_dim = current_dimension(); + Full_cell_handle new_s; - Full_cell_handle old_s = full_cell(f); - Full_cell_handle new_s = new_full_cell(); - const int facet_index = index_of_covertex(f); + std::queue task_queue; + task_queue.push( + IITH_task(f, mirror_index(full_cell(f), index_of_covertex(f))) ); - int i(0); - for( ; i < facet_index; ++i ) - associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); - ++i; // skip facet_index - for( ; i <= cur_dim; ++i ) - associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); - associate_vertex_with_full_cell(new_s, facet_index, v); - set_neighbors( new_s, - facet_index, - neighbor(old_s, facet_index), - mirror_index(old_s, facet_index)); - - // add the new full_cell to the list of new full_cells - *new_full_cells++ = new_s; - - // check all of |Facet f|'s neighbors - for( i = 0; i <= cur_dim; ++i ) + while (!task_queue.empty()) { - if( facet_index == i ) - continue; - // we define a |Rotor| because it makes it easy to rotate around - // in a self contained fashion. The corresponding potential - // boundary facet is Facet(full_cell(rot), index_of_covertex(rot)) - Rotor rot(old_s, i, facet_index); - // |rot| on line above, stands for Candidate Facet - while( ! is_boundary_facet(rot) ) - rot = rotate_rotor(rot); + IITH_task task = task_queue.front(); + task_queue.pop(); + + Full_cell_handle old_s = full_cell(task.boundary_facet); + const int facet_index = index_of_covertex(task.boundary_facet); + + Full_cell_handle outside_neighbor = neighbor(old_s, facet_index); + // Here, "new_s" might actually be a new cell, but it might also be "old_s" + // if it has not been treated already in the meantime + new_s = neighbor(outside_neighbor, task.index_of_inside_cell_in_outside_cell); + // If the cell has not been treated yet + if (old_s == new_s) + { + new_s = new_full_cell(); - // we did find the |i|-th neighbor of Facet(old_s, facet_index)... - // has it already been extruded to center point |v| ? - Full_cell_handle outside = neighbor(full_cell(rot), index_of_covertex(rot)); - Full_cell_handle inside = full_cell(rot); - Vertex_handle m = inside->mirror_vertex(index_of_covertex(rot), current_dimension()); - int index = outside->index(m); - Full_cell_handle new_neighbor = outside->neighbor(index); + int i(0); + for ( ; i < facet_index ; ++i) + associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); + ++i; // skip facet_index + for ( ; i <= cur_dim ; ++i) + associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); + associate_vertex_with_full_cell(new_s, facet_index, v); + set_neighbors(new_s, + facet_index, + neighbor(old_s, facet_index), + mirror_index(old_s, facet_index)); - if( new_neighbor == inside ) - { // not already extruded... we do it recursively - new_neighbor = insert_in_tagged_hole( - v, Facet(full_cell(rot), index_of_covertex(rot)), - new_full_cells); + // add the new full_cell to the list of new full_cells + *new_full_cells++ = new_s; + + // check all of |Facet f|'s neighbors + for (i = 0 ; i <= cur_dim ; ++i) + { + if (facet_index == i) + continue; + // we define a |Rotor| because it makes it easy to rotate around + // in a self contained fashion. The corresponding potential + // boundary facet is Facet(full_cell(rot), index_of_covertex(rot)) + Rotor rot(old_s, i, facet_index); + // |rot| on line above, stands for Candidate Facet + while (!is_boundary_facet(rot)) + rot = rotate_rotor(rot); + + // we did find the |i|-th neighbor of Facet(old_s, facet_index)... + // has it already been extruded to center point |v| ? + Full_cell_handle inside = full_cell(rot); + Full_cell_handle outside = neighbor(inside, index_of_covertex(rot)); + // "m" is the vertex of outside which is not on the boundary + Vertex_handle m = inside->mirror_vertex(index_of_covertex(rot), current_dimension()); // CJTODO: use mirror_index? + // "index" is the index of m in "outside" + int index = outside->index(m); + // new_neighbor is the inside cell which is registered as the neighbor + // of the outside cell => it's either a newly created inside cell or an + // old inside cell which we are about to delete + Full_cell_handle new_neighbor = outside->neighbor(index); + + // Is new_neighbor still the old neighbor? + if (new_neighbor == inside) + { + task_queue.push(IITH_task( + Facet(inside, index_of_covertex(rot)), // boundary facet + index, // index_of_inside_cell_in_outside_cell + new_s, // future_neighbor + i, // new_cell_index_in_future_neighbor + index_of_second_covertex(rot) // index_of_future_neighbor_in_new_cell + )); + } + } + } + + // If there is some neighbor stories to fix + if (task.future_neighbor != Full_cell_handle()) + { + // now the new neighboring full_cell exists, we link both + set_neighbors(new_s, + task.index_of_future_neighbor_in_new_cell, + task.future_neighbor, + task.new_cell_index_in_future_neighbor); } - // now the new neighboring full_cell exists, we link both - set_neighbors(new_s, i, new_neighbor, index_of_second_covertex(rot)); } + return new_s; } From d02296de8317d99d6d73a29d8c7920c0afa2b6f0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 19 Jun 2014 07:52:14 +0200 Subject: [PATCH 039/487] Missing using/typedef + bug fix --- Triangulation/include/CGAL/Regular_triangulation.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index b173136ef65..82c49704516 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -69,6 +69,7 @@ public: // PUBLIC NESTED TYPES typedef typename RTTraits::Bare_point Bare_point; typedef typename RTTraits::Weighted_point Weighted_point; + typedef typename Base::Point_const_iterator Point_const_iterator; typedef typename Base::Vertex_handle Vertex_handle; typedef typename Base::Vertex_iterator Vertex_iterator; typedef typename Base::Vertex_const_handle Vertex_const_handle; @@ -78,6 +79,8 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Full_cell_iterator Full_cell_iterator; typedef typename Base::Full_cell_const_handle Full_cell_const_handle; typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename Base::Finite_full_cell_const_iterator + Finite_full_cell_const_iterator; typedef typename Base::size_type size_type; typedef typename Base::difference_type difference_type; @@ -117,6 +120,8 @@ public: using Base::full_cell; using Base::full_cells_begin; using Base::full_cells_end; + using Base::finite_full_cells_begin; + using Base::finite_full_cells_end; using Base::vertices_begin; using Base::vertices_end; @@ -767,7 +772,6 @@ Regular_triangulation ::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s) { typedef std::vector Full_cell_h_vector; - typedef typename Full_cell_h_vector::iterator SHV_iterator; static Full_cell_h_vector cs; // for storing conflicting full_cells. cs.clear(); // cs.reserve(64); @@ -804,7 +808,7 @@ Regular_triangulation // because the full_cell "s" is assumed to be positively oriented return ON_NEGATIVE_SIDE; // we consider |p| to lie outside the sphere test_points.clear(); - typename Base::Point_const_iterator spit = points_begin(s); + Point_const_iterator spit = points_begin(s); int adjust_sign = -1; for( i = 0; i < current_dimension(); ++i ) { @@ -914,7 +918,7 @@ Regular_triangulation geom_traits().power_test_d_object(); if (side(Point_const_iterator(ch->vertices_begin()), Point_const_iterator(ch->vertices_end()), - opposite_vh->point()) == ON_BOUNDED_SIDE) + opposite_vh->point()) == ON_POSITIVE_SIDE) { if (verbose) CGAL_warning_msg(false, "Non-empty sphere"); From 8ff09b38a0bdbd08af365d4b1f731a18c916b0b8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 19 Jun 2014 07:56:10 +0200 Subject: [PATCH 040/487] Comment fix --- Triangulation/include/CGAL/IO/Triangulation_off_ostream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index a58be847576..b03130f4e95 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -185,7 +185,7 @@ export_triangulation_to_off(std::ostream & os, } else { - // Parse boundary facets + // Parse finite cells for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ; fch != tr.finite_full_cells_end() ; ++fch) { From b32209f6a9bb5c1f0ff31d9dfe73c7203eac5ff7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sat, 5 Jul 2014 06:19:58 +0200 Subject: [PATCH 041/487] Update dont_submit --- Triangulation/dont_submit | 1 - 1 file changed, 1 deletion(-) diff --git a/Triangulation/dont_submit b/Triangulation/dont_submit index f5c7a0a6d72..b2de9879971 100644 --- a/Triangulation/dont_submit +++ b/Triangulation/dont_submit @@ -1,3 +1,2 @@ TODO include/CGAL/Convex_hull.h -include/CGAL/Regular_triangulation.h From 018929fecf2294c3fc83140cfd6337e146458000 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 22 Jul 2014 17:26:55 +0200 Subject: [PATCH 042/487] Replace operator<< for Point_d by output_point --- .../CGAL/IO/Triangulation_off_ostream.h | 54 +++++++++++++------ .../Regular_triangulation_euclidean_traits.h | 50 +++++++++++++++++ 2 files changed, 89 insertions(+), 15 deletions(-) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index b03130f4e95..5bffb964ddb 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -28,28 +28,51 @@ namespace CGAL { -template -std::ostream & -operator<<(std::ostream & os, const typename Wrap::Point_d & p) +namespace Triangulation_IO { - typename K::Cartesian_const_iterator_d it = p.cartesian_begin(); - os << *it; - ++it; - for ( ; it != p.cartesian_end() ; ++it) +// TODO: test if the stream is binary or text? +template +void +output_point(std::ostream & os, const Traits &traits, const P & p) +{ + typedef typename Traits::Compute_coordinate_d Ccd; + const Ccd ccd = traits.compute_coordinate_d_object(); + const int dim = traits.point_dimension_d_object()(p); + if (dim > 0) { - os << " " << *it; + os << ccd(p, 0); + for (int i = 1 ; i < dim ; ++i) + os << " " << CGAL::to_double(ccd(p, i)); } - return os; } -template -std::ostream & -operator<<(std::ostream & os, const typename Wrap::Weighted_point_d & p) +// TODO: test if the stream is binary or text? +/*template +void +input_point(std::istream & is, const Traits &traits, P & p) { - return os << p.point(); -} + typedef typename Traits::FT FT; + std::vector coords; + + std::string line; + for(;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + while (line_sstr >> temp) + coords.push_back(temp); + p = traits.construct_point_d_object()(coords.begin(), coords.end()); +}*/ +} // namespace Triangulation_IO + +// TODO: test if the stream is binary or text? template std::istream & operator>>(std::istream &is, typename Wrap::Point_d & p) @@ -75,6 +98,7 @@ operator>>(std::istream &is, typename Wrap::Point_d & p) return is; } +// TODO: test if the stream is binary or text? template std::istream & operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) @@ -137,7 +161,7 @@ export_triangulation_to_off(std::ostream & os, for(Finite_vertex_iterator it = tr.finite_vertices_begin(); it != tr.finite_vertices_end(); ++it, ++i) { - output << *it; + Triangulation_IO::output_point(output, tr.geom_traits(), it->point()); if (tr.maximal_dimension() == 2) output << " 0"; output << std::endl; diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index e13cd57a5ed..6a4e993ae9a 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -172,7 +172,49 @@ public: return m_kernel.compare_lexicographically_d_object()(pdw(p), pdw(q)); } }; + + //============================================================================= + class Compute_coordinate_d + { + const K &m_kernel; + + public: + typedef FT result_type; + + Compute_coordinate_d(const K &kernel) + : m_kernel(kernel) {} + + result_type operator()( + const Weighted_point_d & p, const int i) const + { + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + auto pp = pdw(p); + auto ddsd = m_kernel.compute_coordinate_d_object(); + ddsd(pp, i); + return m_kernel.compute_coordinate_d_object()(pdw(p), i); + } + }; + + //============================================================================= + + class Point_dimension_d + { + const K &m_kernel; + + public: + typedef int result_type; + + Point_dimension_d(const K &kernel) + : m_kernel(kernel) {} + + result_type operator()( + const Weighted_point_d & p) const + { + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + return m_kernel.point_dimension_d_object()(pdw(p)); + } + }; //============================================================================= // Object creation @@ -198,6 +240,14 @@ public: { return Compare_lexicographically_d(*this); } + Compute_coordinate_d compute_coordinate_d_object() const + { + return Compute_coordinate_d(*this); + } + Point_dimension_d point_dimension_d_object() const + { + return Point_dimension_d(*this); + } }; From 3c8e50e1b2be882bd5b40b50acbdb76c066b52a4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 29 Jul 2014 11:58:08 +0200 Subject: [PATCH 043/487] Remove const& for now (waiting for a better solution from Marc) --- NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h index 68acdd27001..9767f2f2e6b 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h @@ -180,7 +180,7 @@ template struct Compute_cartesian_coordinate { #ifdef CGAL_CXX11 typedef decltype(std::declval()[0]) result_type; #else - typedef RT const& result_type; + typedef RT result_type; // RT const& doesn't work with some LA (Eigen2 for instance) so we // should use plain RT or find a way to detect this. #endif From 96fa41a1e7c16240e824a1de2479d2aaab324c2e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 29 Jul 2014 16:59:50 +0200 Subject: [PATCH 044/487] Add a comment --- Triangulation/include/CGAL/IO/Triangulation_off_ostream.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 5bffb964ddb..590c2a6b0e6 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -72,6 +72,10 @@ input_point(std::istream & is, const Traits &traits, P & p) } // namespace Triangulation_IO +/////////////////////////////////////////////////////////////// +// TODO: replace these operator>> by an "input_point" function +/////////////////////////////////////////////////////////////// + // TODO: test if the stream is binary or text? template std::istream & From b01ebecf5afcb587ed9244fca825d2daa7c51667 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 29 Jul 2014 17:02:16 +0200 Subject: [PATCH 045/487] Data --- .../applications/Triangulation/data/points_2.cin | 4 ++-- .../applications/Triangulation/data/points_3.cin | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Triangulation/applications/Triangulation/data/points_2.cin b/Triangulation/applications/Triangulation/data/points_2.cin index 19b563f4835..5e75591106d 100644 --- a/Triangulation/applications/Triangulation/data/points_2.cin +++ b/Triangulation/applications/Triangulation/data/points_2.cin @@ -4,8 +4,8 @@ 1.3697 1.8296 0.1 0.6722 0.3012 0.15 1.1726 0.1899 0.2 -0.4374 2.8541 100.25 +0.4374 2.8541 0.25 2.5923 0.1904 0.3 -1.3083 2.5462 200.35 +1.3083 2.5462 0.35 1.4981 1.3929 0.4 2.1304 2.055 0.45 \ No newline at end of file diff --git a/Triangulation/applications/Triangulation/data/points_3.cin b/Triangulation/applications/Triangulation/data/points_3.cin index 5ffbc05d517..6b094b18509 100644 --- a/Triangulation/applications/Triangulation/data/points_3.cin +++ b/Triangulation/applications/Triangulation/data/points_3.cin @@ -1,11 +1,11 @@ 3 0.0071 1.6899 2.521 0 -0.3272 1.3694 3.15 100.05 +0.3272 1.3694 3.15 0.05 1.3697 1.8296 2.654 0.1 -0.6722 0.3012 0.1548 100.15 +0.6722 0.3012 0.1548 0.15 1.1726 0.1899 0.3658 0.2 -0.4374 2.8541 1.45894 200.25 +0.4374 2.8541 1.45894 0.25 2.5923 0.1904 0.6971 0.3 -1.3083 2.5462 1.3658 100.35 +1.3083 2.5462 1.3658 0.35 1.4981 1.3929 2.949 0.4 -2.1304 2.055 0.6597455 1.45 \ No newline at end of file +2.1304 2.055 0.6597455 0.45 \ No newline at end of file From 10547ce0e7f52a065b607498abc4cdbe6eb8a867 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 29 Jul 2014 17:05:45 +0200 Subject: [PATCH 046/487] Fix identation + remove useless typedefs --- Triangulation/benchmark/Triangulation/delaunay.cpp | 1 - Triangulation/test/Triangulation/delaunay.cpp | 10 +++++----- Triangulation/test/Triangulation/regular.cpp | 6 ++---- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index ea6c160c807..7d1a5b379ee 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -65,6 +65,5 @@ int main(int argc, char **argv) go<7>(N); go<8>(N); - return 0; } diff --git a/Triangulation/test/Triangulation/delaunay.cpp b/Triangulation/test/Triangulation/delaunay.cpp index e11de0f99be..76cd1914eae 100644 --- a/Triangulation/test/Triangulation/delaunay.cpp +++ b/Triangulation/test/Triangulation/delaunay.cpp @@ -119,11 +119,11 @@ int main(int argc, char **argv) int N = 10; if( argc > 1 ) N = atoi(argv[1]); - //go<5>(N); - //go<4>(N); - //go<3>(N); - go<2>(N); - //go<1>(N); + //go<5>(N); + //go<4>(N); + //go<3>(N); + go<2>(N); + //go<1>(N); cerr << endl; return 0; diff --git a/Triangulation/test/Triangulation/regular.cpp b/Triangulation/test/Triangulation/regular.cpp index 319cb9cec9e..cbfb021a058 100644 --- a/Triangulation/test/Triangulation/regular.cpp +++ b/Triangulation/test/Triangulation/regular.cpp @@ -16,11 +16,7 @@ using namespace std; template void test(const int d, const string & type, const int N) { - typedef typename RTri::Vertex Vertex; - typedef typename RTri::Vertex_handle Vertex_handle; - typedef typename RTri::Full_cell Full_cell; typedef typename RTri::Full_cell_handle Full_cell_handle; - typedef typename RTri::Facet Facet; typedef typename RTri::Face Face; typedef typename RTri::Point Point; typedef typename RTri::Bare_point Bare_point; @@ -98,6 +94,7 @@ void test(const int d, const string & type, const int N) random_shuffle(points.begin(), points.end()); rt.remove(points.begin(), points.end()); assert( rt.is_valid() ); + //std::cerr << ((rt.is_valid(true)) ? "VALID!" : "NOT VALID :(") << std::endl; cerr << rt.number_of_vertices() << " vertices."; // assert( rt.empty() ); NOT YET ! // CLEAR @@ -105,6 +102,7 @@ void test(const int d, const string & type, const int N) assert( -1 == rt.current_dimension() ); assert( rt.empty() ); assert( rt.is_valid() ); + //std::cerr << ((rt.is_valid(true)) ? "VALID!" : "NOT VALID :(") << std::endl; } template< int D > From 9544a1cfb20e98f602611e334e278abee672c239 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 29 Jul 2014 17:23:05 +0200 Subject: [PATCH 047/487] New package: Tangential_complex --- Tangential_complex/dont_submit | 0 .../include/CGAL/Tangential_complex.h | 64 +++++++++++++++++++ .../package_info/Tangential_complex/copyright | 2 + .../Tangential_complex/copyright.txt | 0 .../Tangential_complex/description.txt | 3 + .../Tangential_complex/license.txt | 1 + .../Tangential_complex/maintainer | 1 + .../test/Tangential_complex/CMakeLists.txt | 37 +++++++++++ .../test_tangential_complex.cpp | 12 ++++ 9 files changed, 120 insertions(+) create mode 100644 Tangential_complex/dont_submit create mode 100644 Tangential_complex/include/CGAL/Tangential_complex.h create mode 100644 Tangential_complex/package_info/Tangential_complex/copyright create mode 100644 Tangential_complex/package_info/Tangential_complex/copyright.txt create mode 100644 Tangential_complex/package_info/Tangential_complex/description.txt create mode 100644 Tangential_complex/package_info/Tangential_complex/license.txt create mode 100644 Tangential_complex/package_info/Tangential_complex/maintainer create mode 100644 Tangential_complex/test/Tangential_complex/CMakeLists.txt create mode 100644 Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp diff --git a/Tangential_complex/dont_submit b/Tangential_complex/dont_submit new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h new file mode 100644 index 00000000000..fd0e5d1dc2b --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -0,0 +1,64 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin + + +#ifndef TANGENTIAL_COMPLEX_H +#define TANGENTIAL_COMPLEX_H + +#include + +#include +#include +#include + +#include + +namespace CGAL { + +/// The class Tangential_complex represents a tangential complex +template < + typename Kernel, + int Intrinsic_dimension, + typename Tr = Regular_triangulation > > > +> +class Tangential_complex +{ + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + typedef typename std::vector Tangent_space_base; + +public: + /// Constructor + Tangential_complex() {} + + /// Destructor + ~Tangential_complex() {} + +private: + std::vector m_points; + std::vector m_tangent_spaces; + std::vector m_triangulations; + +}; // /class Tangential_complex + +} // end namespace CGAL + +#endif // TANGENTIAL_COMPLEX_H diff --git a/Tangential_complex/package_info/Tangential_complex/copyright b/Tangential_complex/package_info/Tangential_complex/copyright new file mode 100644 index 00000000000..8932b3233d2 --- /dev/null +++ b/Tangential_complex/package_info/Tangential_complex/copyright @@ -0,0 +1,2 @@ +INRIA Sophia-Antipolis (France) + diff --git a/Tangential_complex/package_info/Tangential_complex/copyright.txt b/Tangential_complex/package_info/Tangential_complex/copyright.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tangential_complex/package_info/Tangential_complex/description.txt b/Tangential_complex/package_info/Tangential_complex/description.txt new file mode 100644 index 00000000000..b8969f7fc3e --- /dev/null +++ b/Tangential_complex/package_info/Tangential_complex/description.txt @@ -0,0 +1,3 @@ +Tangential complex + +This CGAL component provides an implementation of the tangential complex. diff --git a/Tangential_complex/package_info/Tangential_complex/license.txt b/Tangential_complex/package_info/Tangential_complex/license.txt new file mode 100644 index 00000000000..8bb8efcb72b --- /dev/null +++ b/Tangential_complex/package_info/Tangential_complex/license.txt @@ -0,0 +1 @@ +GPL (v3 or later) diff --git a/Tangential_complex/package_info/Tangential_complex/maintainer b/Tangential_complex/package_info/Tangential_complex/maintainer new file mode 100644 index 00000000000..769c1668e20 --- /dev/null +++ b/Tangential_complex/package_info/Tangential_complex/maintainer @@ -0,0 +1 @@ +Clément Jamin \ No newline at end of file diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt new file mode 100644 index 00000000000..7ba896e34c7 --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -0,0 +1,37 @@ +# Created by the script cgal_create_cmake_script +# This is the CMake script for compiling a CGAL application. + + +project( Tangential_complex_test ) + +cmake_minimum_required(VERSION 2.6.2) +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) + if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) + cmake_policy(VERSION 2.8.4) + else() + cmake_policy(VERSION 2.6) + endif() +endif() + +find_package(CGAL QUIET COMPONENTS Core ) + +if ( CGAL_FOUND ) + include( ${CGAL_USE_FILE} ) + include( CGAL_CreateSingleSourceCGALProgram ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + include_directories (BEFORE "../../include") + include_directories (BEFORE "include") + + create_single_source_cgal_program( "test_tangential_complex.cpp" ) + + else() + message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") + endif() + +else() + message(STATUS "This program requires the CGAL library, and will not be compiled.") +endif() + diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp new file mode 100644 index 00000000000..7e912492798 --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -0,0 +1,12 @@ +#include +#include + +int main() +{ + typedef CGAL::Epick_d > Kernel; + const int INTRINSIC_DIMENSION = 2; + + CGAL::Tangential_complex tc; + + return 0; +} \ No newline at end of file From 78428ac2537309111915e778e8f1725671dae1f6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 30 Jul 2014 16:45:28 +0200 Subject: [PATCH 048/487] File renaming --- Triangulation/test/Triangulation/CMakeLists.txt | 1 + .../test/Triangulation/{regular.cpp => test_regular.cpp} | 0 2 files changed, 1 insertion(+) rename Triangulation/test/Triangulation/{regular.cpp => test_regular.cpp} (100%) diff --git a/Triangulation/test/Triangulation/CMakeLists.txt b/Triangulation/test/Triangulation/CMakeLists.txt index 89abb618ce7..4b3674feed2 100644 --- a/Triangulation/test/Triangulation/CMakeLists.txt +++ b/Triangulation/test/Triangulation/CMakeLists.txt @@ -28,6 +28,7 @@ if ( CGAL_FOUND ) include_directories (BEFORE "include") create_single_source_cgal_program( "test_delaunay.cpp" ) + create_single_source_cgal_program( "test_regular.cpp" ) create_single_source_cgal_program( "test_tds.cpp" ) create_single_source_cgal_program( "test_torture.cpp" ) create_single_source_cgal_program( "test_triangulation.cpp" ) diff --git a/Triangulation/test/Triangulation/regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp similarity index 100% rename from Triangulation/test/Triangulation/regular.cpp rename to Triangulation/test/Triangulation/test_regular.cpp From b916d1831907fb36e7abfeaa5ba3a44162a0a51e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 30 Jul 2014 18:07:03 +0200 Subject: [PATCH 049/487] First version of insert_if_in_star that is too restrictive We need to check that star_center is not part of the conflict zone. --- .../include/CGAL/Regular_triangulation.h | 68 ++++++++++++++ .../test/Triangulation/CMakeLists.txt | 6 +- .../Triangulation/test_insert_if_in_star.cpp | 88 +++++++++++++++++++ 3 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 Triangulation/test/Triangulation/test_insert_if_in_star.cpp diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 82c49704516..1f339c38d0a 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -265,6 +265,32 @@ public: Vertex_handle insert_outside_affine_hull(const Weighted_point &); Vertex_handle insert_in_conflicting_cell(const Weighted_point &, const Full_cell_handle); + + Vertex_handle insert_if_in_star(const Weighted_point &, + const Vertex_handle, + const Locate_type, + const Face &, + const Facet &, + const Full_cell_handle); + + Vertex_handle insert_if_in_star( + const Weighted_point & p, const Vertex_handle star_center, + const Full_cell_handle start = Full_cell_handle()) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, start); + return insert_if_in_star(p, star_center, lt, f, ft, s); + } + + Vertex_handle insert_if_in_star( + const Weighted_point & p, const Vertex_handle star_center, + const Vertex_handle hint) + { + CGAL_assertion( Vertex_handle() != hint ); + return insert_if_in_star(p, hint->full_cell()); + } // - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES @@ -780,6 +806,48 @@ Regular_triangulation return insert_in_hole(p, cs.begin(), cs.end(), ft); } +template< typename RTTraits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation +::insert_if_in_star(const Weighted_point & p, + const Vertex_handle star_center, + const Locate_type lt, const Face & f, const Facet & ft, + const Full_cell_handle s) +{ + switch( lt ) + { + case Base::OUTSIDE_AFFINE_HULL: + return insert_outside_affine_hull(p); + break; + case Base::ON_VERTEX: + { + Vertex_handle v = s->vertex(f.index(0)); + v->set_point(p); + return v; + break; + } + default: + if (s->has_vertex(star_center)) + { + if( 1 == current_dimension() ) + { + if( Base::OUTSIDE_CONVEX_HULL == lt ) + { + return insert_outside_convex_hull_1(p, s); + } + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + return v; + } + else + return insert_in_conflicting_cell(p, s); + } + break; + } + + return Vertex_handle(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES // NOT DOCUMENTED diff --git a/Triangulation/test/Triangulation/CMakeLists.txt b/Triangulation/test/Triangulation/CMakeLists.txt index 4b3674feed2..ff378f0b4b1 100644 --- a/Triangulation/test/Triangulation/CMakeLists.txt +++ b/Triangulation/test/Triangulation/CMakeLists.txt @@ -1,7 +1,6 @@ # Created by the script cgal_create_cmake_script # This is the CMake script for compiling a CGAL application. - project( Triangulation_test ) cmake_minimum_required(VERSION 2.6.2) @@ -27,19 +26,18 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") include_directories (BEFORE "include") + create_single_source_cgal_program( "test_triangulation.cpp" ) create_single_source_cgal_program( "test_delaunay.cpp" ) create_single_source_cgal_program( "test_regular.cpp" ) create_single_source_cgal_program( "test_tds.cpp" ) + create_single_source_cgal_program( "test_insert_if_in_star.cpp" ) create_single_source_cgal_program( "test_torture.cpp" ) - create_single_source_cgal_program( "test_triangulation.cpp" ) else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") endif() else() - message(STATUS "This program requires the CGAL library, and will not be compiled.") - endif() diff --git a/Triangulation/test/Triangulation/test_insert_if_in_star.cpp b/Triangulation/test/Triangulation/test_insert_if_in_star.cpp new file mode 100644 index 00000000000..7c392e72633 --- /dev/null +++ b/Triangulation/test/Triangulation/test_insert_if_in_star.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +template +void test(const int d, const string & type, const int N) +{ + typedef typename RTri::Vertex_handle Vertex_handle; + typedef typename RTri::Point Point; + typedef typename RTri::Bare_point Bare_point; + + typedef CGAL::Random_points_in_cube_d Random_points_iterator; + + RTri rt(d); + RTri rt_star_only(d); + cerr << "\nBuilding Regular triangulation of (" << type << d + << ") dimension with " << N << " points\n"; + assert(rt.empty()); + assert(rt_star_only.empty()); + + srand(10); + + // Insert first point (0, 0...) + vector coords(d); + for( int j = 0; j < d; ++j ) + coords[j] = 0; + + Point p = Point( + Bare_point(d, coords.begin(), coords.end()), + static_cast(rand() % 10000)/100000); + + rt.insert(p); + Vertex_handle first_vertex = rt_star_only.insert(p); + + // Insert the other points + for( int i = 1 ; i < N ; ++i ) + { + for( int j = 0; j < d; ++j ) + coords[j] = 10.*(rand() % RAND_MAX)/RAND_MAX - 5.; + + p = Point( + Bare_point(d, coords.begin(), coords.end()), + static_cast(rand() % 10000)/100000); + + rt.insert(p); + rt_star_only.insert_if_in_star(p, first_vertex); + } + + cerr << "\nChecking topology and geometry..." + << (rt.is_valid(true) ? "OK.\n" : "Error.\n"); + + cerr << "\nThe triangulation has current dimension " << rt.current_dimension() + << " and " << rt.number_of_full_cells() << " full cells\n"; + + // Export + std::ofstream off_stream_all("data/test_insert_all.off"); + CGAL::export_triangulation_to_off(off_stream_all, rt); + std::ofstream off_stream_star_only("data/test_insert_if_in_star.off"); + CGAL::export_triangulation_to_off(off_stream_star_only, rt_star_only); +} + +template< int D > +void go(const int N) +{ + //typedef CGAL::Epick_d FK; + typedef CGAL::Epick_d > FK; + typedef CGAL::Regular_triangulation_euclidean_traits Traits; + typedef CGAL::Regular_triangulation Triangulation; + //test(D, "dynamic", N); + test(D, "static", N); +} + +int main(int argc, char **argv) +{ + go<2>(100); + return 0; +} From 5cc88e11e496a3a10d5b2efe90c111d30e64996c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 30 Jul 2014 18:26:44 +0200 Subject: [PATCH 050/487] This version of insert_if_in_star seems to work better At least in 2D --- .../include/CGAL/Regular_triangulation.h | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 1f339c38d0a..7700abd3ffb 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -273,6 +273,10 @@ public: const Facet &, const Full_cell_handle); + Vertex_handle insert_in_conflicting_cell_if_in_star(const Weighted_point &, + const Vertex_handle, + const Full_cell_handle); + Vertex_handle insert_if_in_star( const Weighted_point & p, const Vertex_handle star_center, const Full_cell_handle start = Full_cell_handle()) @@ -827,9 +831,10 @@ Regular_triangulation break; } default: - if (s->has_vertex(star_center)) + { + if( 1 == current_dimension() ) { - if( 1 == current_dimension() ) + if (s->has_vertex(star_center)) { if( Base::OUTSIDE_CONVEX_HULL == lt ) { @@ -839,15 +844,38 @@ Regular_triangulation v->set_point(p); return v; } - else - return insert_in_conflicting_cell(p, s); } - break; + else + return insert_in_conflicting_cell_if_in_star(p, star_center, s); + break; + } } return Vertex_handle(); } +template< typename RTTraits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation +::insert_in_conflicting_cell_if_in_star(const Weighted_point & p, + const Vertex_handle star_center, + const Full_cell_handle s) +{ + typedef std::vector Full_cell_h_vector; + static Full_cell_h_vector cs; // for storing conflicting full_cells. + cs.clear(); + // cs.reserve(64); + std::back_insert_iterator out(cs); + Facet ft = compute_conflict_zone(p, s, out); + Full_cell_h_vector::const_iterator it = cs.begin(), it_end = cs.end(); + for ( ; it != it_end ; ++it) + { + if ((*it)->has_vertex(star_center)) + return insert_in_hole(p, cs.begin(), cs.end(), ft); + } + return Vertex_handle(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES // NOT DOCUMENTED From cc2e0edeb9f9e49d2257cb6c8eafeefce04e343c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 30 Jul 2014 18:32:13 +0200 Subject: [PATCH 051/487] Make the test random + smaller weights Hidden points are not handled for now --- Triangulation/test/Triangulation/test_insert_if_in_star.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation/test/Triangulation/test_insert_if_in_star.cpp b/Triangulation/test/Triangulation/test_insert_if_in_star.cpp index 7c392e72633..47d5b761ae3 100644 --- a/Triangulation/test/Triangulation/test_insert_if_in_star.cpp +++ b/Triangulation/test/Triangulation/test_insert_if_in_star.cpp @@ -28,8 +28,8 @@ void test(const int d, const string & type, const int N) << ") dimension with " << N << " points\n"; assert(rt.empty()); assert(rt_star_only.empty()); - - srand(10); + + srand(static_cast(time(NULL))); // Insert first point (0, 0...) vector coords(d); @@ -51,7 +51,7 @@ void test(const int d, const string & type, const int N) p = Point( Bare_point(d, coords.begin(), coords.end()), - static_cast(rand() % 10000)/100000); + static_cast(rand() % 10000)/1000000); rt.insert(p); rt_star_only.insert_if_in_star(p, first_vertex); From 2ded31716e5cc8f1488af3caf5603dbb03eda556 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 30 Jul 2014 19:00:12 +0200 Subject: [PATCH 052/487] Update test --- .../Triangulation/test_insert_if_in_star.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Triangulation/test/Triangulation/test_insert_if_in_star.cpp b/Triangulation/test/Triangulation/test_insert_if_in_star.cpp index 47d5b761ae3..3621c034fbc 100644 --- a/Triangulation/test/Triangulation/test_insert_if_in_star.cpp +++ b/Triangulation/test/Triangulation/test_insert_if_in_star.cpp @@ -60,14 +60,20 @@ void test(const int d, const string & type, const int N) cerr << "\nChecking topology and geometry..." << (rt.is_valid(true) ? "OK.\n" : "Error.\n"); - cerr << "\nThe triangulation has current dimension " << rt.current_dimension() + cerr << "\nThe triangulation using 'insert' has current dimension " << rt.current_dimension() << " and " << rt.number_of_full_cells() << " full cells\n"; + + cerr << "\nThe triangulation using 'insert_if_in_star' has current dimension " << rt.current_dimension() + << " and " << rt_star_only.number_of_full_cells() << " full cells\n"; // Export - std::ofstream off_stream_all("data/test_insert_all.off"); - CGAL::export_triangulation_to_off(off_stream_all, rt); - std::ofstream off_stream_star_only("data/test_insert_if_in_star.off"); - CGAL::export_triangulation_to_off(off_stream_star_only, rt_star_only); + if (d <= 3) + { + std::ofstream off_stream_all("data/test_insert_all.off"); + CGAL::export_triangulation_to_off(off_stream_all, rt); + std::ofstream off_stream_star_only("data/test_insert_if_in_star.off"); + CGAL::export_triangulation_to_off(off_stream_star_only, rt_star_only); + } } template< int D > From f466414a7529708cb971301a1c5f16e2e071cba5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Sep 2014 18:33:04 +0200 Subject: [PATCH 053/487] Fix a bug in the copy-constructor of TDS When the dimension is -1, there is one vertex: the infinite vertex. --- Triangulation/include/CGAL/Triangulation_data_structure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 583f798446e..afd07eea7bb 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -195,7 +195,7 @@ public: cto = full_cells_begin(); while( cto != full_cells_end() ) { - for( int i = 0; i <= current_dimension(); ++i ) + for( int i = 0; i <= (std::max)(0, current_dimension()); ++i ) { associate_vertex_with_full_cell(cto, i, vmap[cto->vertex(i)]); cto->set_neighbor(i, cmap[cto->neighbor(i)]); From 429e992570acc3d65c1eae940ff9a679b7006e81 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Sep 2014 18:33:04 +0200 Subject: [PATCH 054/487] Fix a bug in the copy-constructor of TDS When the dimension is -1, there is one vertex: the infinite vertex. (cherry picked from commit f466414a7529708cb971301a1c5f16e2e071cba5) --- Triangulation/include/CGAL/Triangulation_data_structure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 583f798446e..afd07eea7bb 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -195,7 +195,7 @@ public: cto = full_cells_begin(); while( cto != full_cells_end() ) { - for( int i = 0; i <= current_dimension(); ++i ) + for( int i = 0; i <= (std::max)(0, current_dimension()); ++i ) { associate_vertex_with_full_cell(cto, i, vmap[cto->vertex(i)]); cto->set_neighbor(i, cmap[cto->neighbor(i)]); From 07e40bd28cae7a479d9bc305d0b637d3cbf6e853 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Sep 2014 18:43:43 +0200 Subject: [PATCH 055/487] Builds the local triangulations --- .../include/CGAL/Tangential_complex.h | 121 +++++++++++++++++- .../test_tangential_complex.cpp | 14 +- 2 files changed, 126 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fd0e5d1dc2b..c7528ba5ac0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -35,27 +35,134 @@ namespace CGAL { /// The class Tangential_complex represents a tangential complex template < typename Kernel, - int Intrinsic_dimension, + int Intrinsic_dimension, typename Tr = Regular_triangulation > > > > class Tangential_complex { - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Vector_d Vector; - typedef typename std::vector Tangent_space_base; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + + typedef Tr Triangulation; + typedef typename Triangulation::Point Tr_point; + typedef typename Triangulation::Bare_point Tr_bare_point; + typedef typename Triangulation::Vertex_handle Tr_vertex_handle; + + typedef typename std::vector Tangent_space_base; + + typedef typename std::vector Point_container; + typedef typename std::vector Tr_container; + typedef typename std::vector TS_container; + + // Stores the index of the original Point in the ambient space + struct Tr_point_with_index + : public Tr_point + { + Tr_point_with_index(const Tr_point &p, std::size_t i) + : Tr_point(p), index(i) {} + + std::size_t index; + }; public: /// Constructor Tangential_complex() {} + + /// Constructor for a range of points + template + Tangential_complex(InputIterator first, InputIterator last) + : m_points(first, last) {} /// Destructor ~Tangential_complex() {} + void compute_tangential_complex() + { + Point_container::const_iterator it_p = m_points.begin(); + Point_container::const_iterator it_p_end = m_points.end(); + // For each point p in ambient space + for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) + { + m_triangulations.push_back(Triangulation(Intrinsic_dimension)); + Triangulation &local_tr = m_triangulations.back(); + + // Estimate the tangent space + Tangent_space_base ts = compute_tangential_space(*it_p); + + // Insert p + Tr_point wp = project_point(*it_p, ts); + Tr_point_with_index tpwi(wp, i); + Tr_vertex_handle vh = local_tr.insert(tpwi); + + // Build a minimal triangulation in the tangent space + // (we only need the star of p) + Point_container::const_iterator it2_p = m_points.begin(); + for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) + { + // ith point = p, which is already inserted + if (j != i) + { + Tr_point wp = project_point(*it2_p, ts); + Tr_point_with_index tpwi(wp, j); + local_tr.insert_if_in_star(tpwi, vh); + } + } + } + } + private: - std::vector m_points; - std::vector m_tangent_spaces; - std::vector m_triangulations; + Tangent_space_base compute_tangential_space(const Point &p) const + { + Tangent_space_base ts; + ts.reserve(Intrinsic_dimension); + // CJTODO: this is only for a sphere in R^3 + Vector n = Kernel().point_to_vector_d_object()(p); // CJTODO: change that? + Vector t1(-p[1] - p[2], p[0], p[0]); + Vector t2(p[1] * t1[2] - p[2] * t1[1], + p[2] * t1[0] - p[0] * t1[2], + p[0] * t1[1] - p[1] * t1[0]); + + Kernel k; + Get_functor::type sqlen(k); + //Get_functor::type scale(k); + //ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); + //ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); + + FT t1_len = CGAL::sqrt(sqlen(t1)); + FT t2_len = CGAL::sqrt(sqlen(t2)); + for (int i = 0 ; i < Ambient_dimension::value ; ++i) + { + t1[i] /= t1_len; + t2[i] /= t2_len; + } + ts.push_back(t1); + ts.push_back(t2); + + return ts; + } + + Tr_point project_point(const Point &p, const Tangent_space_base &ts) const + { + std::vector coords; + coords.reserve(Intrinsic_dimension); + for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) + { + //coords[i] = Kernel().point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that + Kernel k; + Get_functor::type scp(k); + coords.push_back(scp(k.point_to_vector_d_object()(p), ts[i])); + } + + return Tr_point( + Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), 0); // CJTODO: poids + } + +private: + Point_container m_points; + TS_container m_tangent_spaces; + Tr_container m_triangulations; }; // /class Tangential_complex diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 7e912492798..0968583bf73 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -1,12 +1,22 @@ #include #include +#include int main() { - typedef CGAL::Epick_d > Kernel; + typedef CGAL::Epick_d > Kernel; + typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; - CGAL::Tangential_complex tc; + CGAL::Random_points_on_sphere_3 generator(3.0); + std::vector points; + points.reserve(50); + for (int i = 0; i != 50; ++i) + points.push_back(*generator++); + + CGAL::Tangential_complex tc( + points.begin(), points.end()); + tc.compute_tangential_complex(); return 0; } \ No newline at end of file From 589730219224ebdabde1bc81093362a7af1a0472 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 3 Sep 2014 19:05:13 +0200 Subject: [PATCH 056/487] One more step towards the Tangential complex --- .../include/CGAL/Tangential_complex.h | 210 ++++++++++++++++-- .../test_tangential_complex.cpp | 12 +- 2 files changed, 197 insertions(+), 25 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c7528ba5ac0..0b8dd2d851b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -28,7 +28,12 @@ #include #include +#include // CJTODO TEMP + #include +#include +#include +#include namespace CGAL { @@ -36,8 +41,21 @@ namespace CGAL { template < typename Kernel, int Intrinsic_dimension, - typename Tr = Regular_triangulation > > > + typename Tr = Regular_triangulation + < + Regular_triangulation_euclidean_traits< + Epick_d > >, + + Triangulation_data_structure + < + typename Regular_triangulation_euclidean_traits< + Epick_d > >::Dimension, + Triangulation_vertex > >, std::size_t >, + Triangulation_full_cell > > > + > + > > class Tangential_complex { @@ -46,25 +64,28 @@ class Tangential_complex typedef typename Kernel::Vector_d Vector; typedef Tr Triangulation; + typedef typename Triangulation::Geom_traits Tr_traits; typedef typename Triangulation::Point Tr_point; typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; + typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename std::vector Tangent_space_base; + typedef std::pair Tr_and_VH; typedef typename std::vector Point_container; - typedef typename std::vector Tr_container; + typedef typename std::vector Tr_container; typedef typename std::vector TS_container; // Stores the index of the original Point in the ambient space - struct Tr_point_with_index + /*struct Tr_point_with_index : public Tr_point { Tr_point_with_index(const Tr_point &p, std::size_t i) : Tr_point(p), index(i) {} std::size_t index; - }; + };*/ public: /// Constructor @@ -80,40 +101,165 @@ public: void compute_tangential_complex() { + Tr_traits traits; // CJTODO: use the Triangulation's traits instance + + // We need to do that because we don't want the container to copy the + // already-computed triangulations (while resizing) since it would + // invalidate the vertex handles stored beside the triangulations + m_triangulations.reserve(m_points.size()); + m_tangent_spaces.reserve(m_points.size()); + Point_container::const_iterator it_p = m_points.begin(); Point_container::const_iterator it_p_end = m_points.end(); // For each point p in ambient space for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) { - m_triangulations.push_back(Triangulation(Intrinsic_dimension)); - Triangulation &local_tr = m_triangulations.back(); + m_triangulations.push_back(std::make_pair( + Triangulation(Intrinsic_dimension), + Tr_vertex_handle())); + Triangulation &local_tr = m_triangulations.back().first; + Tr_vertex_handle ¢er_vertex = m_triangulations.back().second; // Estimate the tangent space - Tangent_space_base ts = compute_tangential_space(*it_p); + m_tangent_spaces.push_back(compute_tangent_space(*it_p)); - // Insert p - Tr_point wp = project_point(*it_p, ts); - Tr_point_with_index tpwi(wp, i); - Tr_vertex_handle vh = local_tr.insert(tpwi); - + //*************************************************** // Build a minimal triangulation in the tangent space // (we only need the star of p) + //*************************************************** + + // First, compute the projected points + std::vector projected_points; + FT max_squared_weight = 0; + projected_points.reserve(m_points.size() - 1); Point_container::const_iterator it2_p = m_points.begin(); for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) { // ith point = p, which is already inserted if (j != i) { - Tr_point wp = project_point(*it2_p, ts); - Tr_point_with_index tpwi(wp, j); - local_tr.insert_if_in_star(tpwi, vh); + Tr_point wp = project_point(*it2_p, *it_p, m_tangent_spaces.back()); + projected_points.push_back(wp); + FT w = traits.point_weight_d_object()(wp); + if (w > max_squared_weight) + max_squared_weight = w; } } + + // Now we can insert the points + + // Insert p + Tr_point wp = traits.construct_weighted_point_d_object()( + traits.construct_point_d_object()(0, 0), + CGAL::sqrt(max_squared_weight)); + center_vertex = local_tr.insert(wp); + center_vertex->data() = i; + + // Insert the other points + std::vector::const_iterator it_wp = projected_points.begin(); + it2_p = m_points.begin(); + for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) + { + // ith point = p, which is already inserted + if (j != i) + { + FT w = CGAL::sqrt(max_squared_weight - traits.point_weight_d_object()(*it_wp)); + std::cerr << w << std::endl; + Tr_point wp = traits.construct_weighted_point_d_object()( + traits.point_drop_weight_d_object()(*it_wp), + w); + /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); + Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ + + Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); + if (vh != Tr_vertex_handle()) + vh->data() = j; + ++it_wp; + } + } + + // CJTODO + std::cerr << "\nChecking topology and geometry..." + << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); + std::stringstream sstr; + sstr << "data/local_tri_" << i << ".off"; + std::ofstream off_stream_tr(sstr.str()); + CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } } + std::ostream &export_to_off(std::ostream & os) + { + const int ambient_dim = Ambient_dimension::value; + if (ambient_dim < 2 || ambient_dim > 3) + { + std::cerr << "Error: export_to_off => ambient dimension should be 2 or 3."; + os << "Error: export_to_off => ambient dimension should be 2 or 3."; + return os; + } + + if (Intrinsic_dimension < 1 || Intrinsic_dimension > 3) + { + std::cerr << "Error: export_to_off => intrinsic dimension should be between 1 and 3."; + os << "Error: export_to_off => intrinsic dimension should be between 1 and 3."; + return os; + } + + std::stringstream output; + + //******** VERTICES ************ + + Point_container::const_iterator it_p = m_points.begin(); + Point_container::const_iterator it_p_end = m_points.end(); + // For each point p + for ( ; it_p != it_p_end ; ++it_p) + { + int i = 0; + for ( ; i < ambient_dim ; ++i) + output << (*it_p)[i] << " "; + if (i == 2) + output << "0"; + output << std::endl; + } + + //******** CELLS ************ + + std::size_t num_cells = 0; + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + const Triangulation &tr = it_tr->first; + Tr_vertex_handle center_vh = it_tr->second; + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each triangulation + for ( ; it_c != it_c_end ; ++it_c) + { + output << Intrinsic_dimension + 1 << " "; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + output << (*it_c)->vertex(i)->data() << " "; + output << std::endl; + ++num_cells; + } + } + + os << "OFF \n" + << m_points.size() << " " + << num_cells << " " + << "0 \n" + << output.str(); + + return os; + } + private: - Tangent_space_base compute_tangential_space(const Point &p) const + Tangent_space_base compute_tangent_space(const Point &p) const { Tangent_space_base ts; ts.reserve(Intrinsic_dimension); @@ -143,26 +289,44 @@ private: return ts; } - Tr_point project_point(const Point &p, const Tangent_space_base &ts) const + // Project the point in the tangent space + // The weight will be the squared distance between p and the projection of p + Tr_point project_point(const Point &p, const Point &origin, + const Tangent_space_base &ts) const { + Kernel k; + Get_functor::type inner_pdct(k); + Get_functor::type diff_points(k); + std::vector coords; + // Ambiant-space coords of the projected point + std::vector p_proj(Ambient_dimension::value, 0); coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { //coords[i] = Kernel().point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that - Kernel k; - Get_functor::type scp(k); - coords.push_back(scp(k.point_to_vector_d_object()(p), ts[i])); + // Compute the inner product p * ts[i] + Vector v = diff_points(p, origin); + FT coord = inner_pdct(v, ts[i]); + coords.push_back(coord); + + // p_proj += coord * v; + for (int i = 0 ; i < Ambient_dimension::value ; ++i) + p_proj[i] += coord * v[i]; } + Point projected_pt(Ambient_dimension::value, + p_proj.begin(), p_proj.end()); return Tr_point( - Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), 0); // CJTODO: poids + Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), + k.squared_distance_d_object()(p, projected_pt)); } private: Point_container m_points; TS_container m_tangent_spaces; - Tr_container m_triangulations; + Tr_container m_triangulations; // Contains the triangulations + // and their center vertex }; // /class Tangential_complex diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 0968583bf73..eba3478a1bd 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -2,21 +2,29 @@ #include #include +#include + int main() { typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; + const int NUM_POINTS = 50; CGAL::Random_points_on_sphere_3 generator(3.0); std::vector points; - points.reserve(50); - for (int i = 0; i != 50; ++i) + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) points.push_back(*generator++); CGAL::Tangential_complex tc( points.begin(), points.end()); tc.compute_tangential_complex(); + + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str()); + tc.export_to_off(off_stream); return 0; } \ No newline at end of file From 855a475918bae9558b938094066b8f7a9742aa1e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 09:59:02 +0200 Subject: [PATCH 057/487] Fix a bug in the computation of the projected point + debugging output --- .../include/CGAL/Tangential_complex.h | 27 ++++++++++++++----- .../test_tangential_complex.cpp | 7 +++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 0b8dd2d851b..13f89f437a1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -154,6 +154,7 @@ public: CGAL::sqrt(max_squared_weight)); center_vertex = local_tr.insert(wp); center_vertex->data() = i; + std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; // Insert the other points std::vector::const_iterator it_wp = projected_points.begin(); @@ -163,17 +164,28 @@ public: // ith point = p, which is already inserted if (j != i) { - FT w = CGAL::sqrt(max_squared_weight - traits.point_weight_d_object()(*it_wp)); - std::cerr << w << std::endl; + FT squared_dist_to_tangent_plane = + traits.point_weight_d_object()(*it_wp); + FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); Tr_point wp = traits.construct_weighted_point_d_object()( traits.point_drop_weight_d_object()(*it_wp), w); /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ + // CJTODO TEMP + if (squared_dist_to_tangent_plane < 9) + { Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); if (vh != Tr_vertex_handle()) + { + std::cerr << "Inserted point of weight " << w + << "\t(dist to tangent plane = " + << CGAL::sqrt(squared_dist_to_tangent_plane) + << ")" << std::endl; vh->data() = j; + } + } ++it_wp; } } @@ -264,12 +276,15 @@ private: Tangent_space_base ts; ts.reserve(Intrinsic_dimension); // CJTODO: this is only for a sphere in R^3 - Vector n = Kernel().point_to_vector_d_object()(p); // CJTODO: change that? Vector t1(-p[1] - p[2], p[0], p[0]); Vector t2(p[1] * t1[2] - p[2] * t1[1], p[2] * t1[0] - p[0] * t1[2], p[0] * t1[1] - p[1] * t1[0]); + // CJTODO: this is for a plane (test) + //Vector t1(1, 0, 0); + //Vector t2(0, 1, 0); + // Normalize t1 and t2 Kernel k; Get_functor::type sqlen(k); //Get_functor::type scale(k); @@ -300,7 +315,7 @@ private: std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(Ambient_dimension::value, 0); + std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { @@ -311,8 +326,8 @@ private: coords.push_back(coord); // p_proj += coord * v; - for (int i = 0 ; i < Ambient_dimension::value ; ++i) - p_proj[i] += coord * v[i]; + for (int j = 0 ; j < Ambient_dimension::value ; ++j) + p_proj[i] += coord * ts[i][j]; } Point projected_pt(Ambient_dimension::value, diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index eba3478a1bd..d115652f41e 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -10,12 +10,19 @@ int main() typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; +#ifdef _DEBUG const int NUM_POINTS = 50; +#else + const int NUM_POINTS = 500; +#endif CGAL::Random_points_on_sphere_3 generator(3.0); std::vector points; points.reserve(NUM_POINTS); for (int i = 0 ; i != NUM_POINTS ; ++i) + { points.push_back(*generator++); + //points.push_back(Point((double)(rand()%10000)/5000, (double)(rand()%10000)/5000, 0.)); // CJTODO : plane + } CGAL::Tangential_complex tc( points.begin(), points.end()); From ee825951d20dc60a2113b85e0fcd08e45ee49d5d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 16:06:29 +0200 Subject: [PATCH 058/487] Removed two local static variables Local static variables are not thread-safe --- Triangulation/include/CGAL/Delaunay_triangulation.h | 5 ++--- Triangulation/include/CGAL/Regular_triangulation.h | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 2397f0c8c42..a4cd4ef7333 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -739,9 +739,8 @@ Delaunay_triangulation ::insert_in_conflicting_cell(const Point & p, const Full_cell_handle s) { typedef std::vector Full_cell_h_vector; - static Full_cell_h_vector cs; // for storing conflicting full_cells. - cs.clear(); - // cs.reserve(64); + Full_cell_h_vector cs; // for storing conflicting full_cells. + cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); return insert_in_hole(p, cs.begin(), cs.end(), ft); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 7700abd3ffb..1ff94456e49 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -802,9 +802,8 @@ Regular_triangulation ::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s) { typedef std::vector Full_cell_h_vector; - static Full_cell_h_vector cs; // for storing conflicting full_cells. - cs.clear(); - // cs.reserve(64); + Full_cell_h_vector cs; // for storing conflicting full_cells. + cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); return insert_in_hole(p, cs.begin(), cs.end(), ft); From dfb38ed1af52d9faaa113bf26435e7ac65711080 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 17:05:18 +0200 Subject: [PATCH 059/487] Do not insert hidden points Hidden points are not handled for now --- Triangulation/include/CGAL/Regular_triangulation.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 1ff94456e49..2758d6b2539 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -806,7 +806,11 @@ Regular_triangulation cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); - return insert_in_hole(p, cs.begin(), cs.end(), ft); + // The conflict zone is empty if the point is hidden + if (!cs.empty()) + return insert_in_hole(p, cs.begin(), cs.end(), ft); + else + return Vertex_handle(); } template< typename RTTraits, typename TDS > @@ -981,7 +985,12 @@ Regular_triangulation Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); Conflict_traversal_pred_in_fullspace tp(*this, c); - return tds().gather_full_cells(s, tp, out); + // If p is not in conflict with s, then p is hidden + // => we don't insert it (CJTODO: handle hidden points) + if (!c(s)) + return Facet(); + else + return tds().gather_full_cells(s, tp, out); } } From 64674627c6253159b1792ac367dcbb2c68f27ce3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 17:05:35 +0200 Subject: [PATCH 060/487] Test if the triangulation is valid --- .../applications/Triangulation_2/points_to_RT2_to_off.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp b/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp index f7a18fb81cb..c2989d5a902 100644 --- a/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp +++ b/Triangulation_2/applications/Triangulation_2/points_to_RT2_to_off.cpp @@ -21,6 +21,7 @@ int main() wpoints.push_back(wp); Regular_triangulation rt(wpoints.begin(), wpoints.end()); + CGAL_assertion(rt.is_valid(true)); std::ofstream off_stream("data/rt2.off"); CGAL::export_triangulation_2_to_off(off_stream, rt); return 0; From 0ab8ef78044c5dc647279654de0e596376246acb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 17:05:18 +0200 Subject: [PATCH 061/487] Do not insert hidden points Hidden points are not handled for now (cherry picked from commit dfb38ed1af52d9faaa113bf26435e7ac65711080) --- Triangulation/include/CGAL/Regular_triangulation.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 7700abd3ffb..0e5b9cd6f26 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -807,7 +807,11 @@ Regular_triangulation // cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); - return insert_in_hole(p, cs.begin(), cs.end(), ft); + // The conflict zone is empty if the point is hidden + if (!cs.empty()) + return insert_in_hole(p, cs.begin(), cs.end(), ft); + else + return Vertex_handle(); } template< typename RTTraits, typename TDS > @@ -982,7 +986,12 @@ Regular_triangulation Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); Conflict_traversal_pred_in_fullspace tp(*this, c); - return tds().gather_full_cells(s, tp, out); + // If p is not in conflict with s, then p is hidden + // => we don't insert it (CJTODO: handle hidden points) + if (!c(s)) + return Facet(); + else + return tds().gather_full_cells(s, tp, out); } } From 4024f61c814ac968f177f52bd897a893af9245ca Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 17:33:02 +0200 Subject: [PATCH 062/487] Commented out some debug code --- .../include/CGAL/Tangential_complex.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 13f89f437a1..7534d643289 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -155,6 +155,10 @@ public: center_vertex = local_tr.insert(wp); center_vertex->data() = i; std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; + + /*std::cerr << 0 << " " + << 0 << " " + << CGAL::sqrt(max_squared_weight) << std::endl;*/ // Insert the other points std::vector::const_iterator it_wp = projected_points.begin(); @@ -173,16 +177,19 @@ public: /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ - // CJTODO TEMP - if (squared_dist_to_tangent_plane < 9) + // CJTODO TEMP: remove this if (but not the content!) + //if (squared_dist_to_tangent_plane < 9) { Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); if (vh != Tr_vertex_handle()) { - std::cerr << "Inserted point of weight " << w + /*std::cerr << "Inserted point of weight " << w << "\t(dist to tangent plane = " << CGAL::sqrt(squared_dist_to_tangent_plane) - << ")" << std::endl; + << ")" << std::endl;*/ + /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " + << traits.point_drop_weight_d_object()(*it_wp)[1] << " " + << w << std::endl;*/ vh->data() = j; } } @@ -193,10 +200,10 @@ public: // CJTODO std::cerr << "\nChecking topology and geometry..." << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); - std::stringstream sstr; + /*std::stringstream sstr; sstr << "data/local_tri_" << i << ".off"; std::ofstream off_stream_tr(sstr.str()); - CGAL::export_triangulation_to_off(off_stream_tr, local_tr); + CGAL::export_triangulation_to_off(off_stream_tr, local_tr);*/ } } From 41c4a174247ee94c4bb824dd5ed6d3b3e19773c9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 18:57:57 +0200 Subject: [PATCH 063/487] Fix the way we use the kernel and the traits --- .../include/CGAL/Tangential_complex.h | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7534d643289..234d2f99c89 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -64,7 +64,6 @@ class Tangential_complex typedef typename Kernel::Vector_d Vector; typedef Tr Triangulation; - typedef typename Triangulation::Geom_traits Tr_traits; typedef typename Triangulation::Point Tr_point; typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; @@ -89,20 +88,20 @@ class Tangential_complex public: /// Constructor - Tangential_complex() {} + Tangential_complex(const Kernel &k = Kernel()) + : m_k(k){} /// Constructor for a range of points template - Tangential_complex(InputIterator first, InputIterator last) - : m_points(first, last) {} + Tangential_complex(InputIterator first, InputIterator last, + const Kernel &k = Kernel()) + : m_k(k), m_points(first, last) {} /// Destructor ~Tangential_complex() {} void compute_tangential_complex() { - Tr_traits traits; // CJTODO: use the Triangulation's traits instance - // We need to do that because we don't want the container to copy the // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations @@ -118,6 +117,7 @@ public: Triangulation(Intrinsic_dimension), Tr_vertex_handle())); Triangulation &local_tr = m_triangulations.back().first; + const Geom_traits &local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations.back().second; // Estimate the tangent space @@ -140,7 +140,7 @@ public: { Tr_point wp = project_point(*it2_p, *it_p, m_tangent_spaces.back()); projected_points.push_back(wp); - FT w = traits.point_weight_d_object()(wp); + FT w = local_tr_traits.point_weight_d_object()(wp); if (w > max_squared_weight) max_squared_weight = w; } @@ -149,8 +149,8 @@ public: // Now we can insert the points // Insert p - Tr_point wp = traits.construct_weighted_point_d_object()( - traits.construct_point_d_object()(0, 0), + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(0, 0), CGAL::sqrt(max_squared_weight)); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -169,10 +169,10 @@ public: if (j != i) { FT squared_dist_to_tangent_plane = - traits.point_weight_d_object()(*it_wp); + local_tr_traits.point_weight_d_object()(*it_wp); FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); - Tr_point wp = traits.construct_weighted_point_d_object()( - traits.point_drop_weight_d_object()(*it_wp), + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.point_drop_weight_d_object()(*it_wp), w); /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ @@ -292,9 +292,8 @@ private: //Vector t2(0, 1, 0); // Normalize t1 and t2 - Kernel k; - Get_functor::type sqlen(k); - //Get_functor::type scale(k); + Get_functor::type sqlen(m_k); + //Get_functor::type scale(m_k); //ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); //ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); @@ -316,9 +315,8 @@ private: Tr_point project_point(const Point &p, const Point &origin, const Tangent_space_base &ts) const { - Kernel k; - Get_functor::type inner_pdct(k); - Get_functor::type diff_points(k); + Get_functor::type inner_pdct(m_k); + Get_functor::type diff_points(m_k); std::vector coords; // Ambiant-space coords of the projected point @@ -326,7 +324,7 @@ private: coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { - //coords[i] = Kernel().point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that + //coords[i] = m_k.point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that // Compute the inner product p * ts[i] Vector v = diff_points(p, origin); FT coord = inner_pdct(v, ts[i]); @@ -341,10 +339,11 @@ private: p_proj.begin(), p_proj.end()); return Tr_point( Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), - k.squared_distance_d_object()(p, projected_pt)); + m_k.squared_distance_d_object()(p, projected_pt)); } private: + const Kernel m_k; Point_container m_points; TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations From 7ca16e3aeae15d801fb856cf5a5d35c9820c1d1f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 19:24:29 +0200 Subject: [PATCH 064/487] Clean-up --- Tangential_complex/include/CGAL/Tangential_complex.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 234d2f99c89..a910a3aa933 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -177,9 +177,6 @@ public: /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ - // CJTODO TEMP: remove this if (but not the content!) - //if (squared_dist_to_tangent_plane < 9) - { Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); if (vh != Tr_vertex_handle()) { @@ -192,7 +189,6 @@ public: << w << std::endl;*/ vh->data() = j; } - } ++it_wp; } } From ce2ee270a0c64e6f13b73fe07bdce82a5d3a566a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 07:14:17 +0200 Subject: [PATCH 065/487] Code and comments clean-up --- .../include/CGAL/Tangential_complex.h | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index a910a3aa933..3acc9a1e857 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -180,10 +180,6 @@ public: Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); if (vh != Tr_vertex_handle()) { - /*std::cerr << "Inserted point of weight " << w - << "\t(dist to tangent plane = " - << CGAL::sqrt(squared_dist_to_tangent_plane) - << ")" << std::endl;*/ /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " << traits.point_drop_weight_d_object()(*it_wp)[1] << " " << w << std::endl;*/ @@ -193,13 +189,14 @@ public: } } - // CJTODO + // CJTODO DEBUG std::cerr << "\nChecking topology and geometry..." << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); - /*std::stringstream sstr; - sstr << "data/local_tri_" << i << ".off"; - std::ofstream off_stream_tr(sstr.str()); - CGAL::export_triangulation_to_off(off_stream_tr, local_tr);*/ + // DEBUG: output the local mesh into an OFF file + //std::stringstream sstr; + //sstr << "data/local_tri_" << i << ".off"; + //std::ofstream off_stream_tr(sstr.str()); + //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } } @@ -289,10 +286,13 @@ private: // Normalize t1 and t2 Get_functor::type sqlen(m_k); + + // CJTODO: use this when Scaled_vector is fixed //Get_functor::type scale(m_k); //ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); //ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); + // ****** Temporary code ******* FT t1_len = CGAL::sqrt(sqlen(t1)); FT t2_len = CGAL::sqrt(sqlen(t2)); for (int i = 0 ; i < Ambient_dimension::value ; ++i) @@ -302,6 +302,7 @@ private: } ts.push_back(t1); ts.push_back(t2); + // ****** /Temporary code ******* return ts; } @@ -320,7 +321,6 @@ private: coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { - //coords[i] = m_k.point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that // Compute the inner product p * ts[i] Vector v = diff_points(p, origin); FT coord = inner_pdct(v, ts[i]); From e41484a3f0336f10124f63203e27cd200d4e8493 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 07:43:31 +0200 Subject: [PATCH 066/487] Pass-by-ref the traits --- Triangulation/include/CGAL/Triangulation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 4874d8bea98..916e8961a4f 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -255,7 +255,7 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS - Triangulation(int dim, const Geom_traits k = Geom_traits()) + Triangulation(int dim, const Geom_traits &k = Geom_traits()) : tds_(dim) , kernel_(k) , infinity_() @@ -276,7 +276,7 @@ public: Triangulation( int dim, const std::pair &preset_flat_orientation, - const Geom_traits k = Geom_traits()) + const Geom_traits &k = Geom_traits()) : tds_(dim) , kernel_(k) , infinity_() From ec7f3a6fd3b77bba5113552bf46ef04f86fad6d5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 07:44:44 +0200 Subject: [PATCH 067/487] Pass-by-ref the traits + slightly better handling of hidden points (WIP) --- .../include/CGAL/Delaunay_triangulation.h | 4 +- .../include/CGAL/Regular_triangulation.h | 41 +++++++++++-------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index a4cd4ef7333..3cb65fff2d1 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -150,7 +150,7 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS - Delaunay_triangulation(int dim, const Geom_traits k = Geom_traits()) + Delaunay_triangulation(int dim, &const Geom_traits k = Geom_traits()) : Base(dim, k) { } @@ -163,7 +163,7 @@ public: Delaunay_triangulation( int dim, const std::pair &preset_flat_orientation, - const Geom_traits k = Geom_traits()) + const Geom_traits &k = Geom_traits()) : Base(dim, preset_flat_orientation, k) { } diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 2758d6b2539..e1280f5e2a3 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -152,7 +152,7 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS - Regular_triangulation(int dim, const Geom_traits k = Geom_traits()) + Regular_triangulation(int dim, const Geom_traits &k = Geom_traits()) : Base(dim, k) { } @@ -165,7 +165,7 @@ public: Regular_triangulation( int dim, const std::pair &preset_flat_orientation, - const Geom_traits k = Geom_traits()) + const Geom_traits &k = Geom_traits()) : Base(dim, preset_flat_orientation, k) { } @@ -391,6 +391,10 @@ private: Conflict_traversal_pred_in_subspace; typedef Conflict_traversal_predicate Conflict_traversal_pred_in_fullspace; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MEMBER VARIABLES + std::vector m_hidden_points; + }; // class Regular_triangulation @@ -802,15 +806,25 @@ Regular_triangulation ::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s) { typedef std::vector Full_cell_h_vector; - Full_cell_h_vector cs; // for storing conflicting full_cells. - cs.reserve(64); - std::back_insert_iterator out(cs); - Facet ft = compute_conflict_zone(p, s, out); - // The conflict zone is empty if the point is hidden - if (!cs.empty()) - return insert_in_hole(p, cs.begin(), cs.end(), ft); - else + + Orientation_d ori = geom_traits().orientation_d_object(); + Power_test_d side = geom_traits().power_test_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + // If p is not in conflict with s, then p is hidden + // => we don't insert it (CJTODO: handle hidden points) + if (!c(s)) + { + m_hidden_points.push_back(p); return Vertex_handle(); + } + else + { + Full_cell_h_vector cs; // for storing conflicting full_cells. + cs.reserve(64); + std::back_insert_iterator out(cs); + Facet ft = compute_conflict_zone(p, s, out); + return insert_in_hole(p, cs.begin(), cs.end(), ft); + } } template< typename RTTraits, typename TDS > @@ -985,12 +999,7 @@ Regular_triangulation Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); Conflict_traversal_pred_in_fullspace tp(*this, c); - // If p is not in conflict with s, then p is hidden - // => we don't insert it (CJTODO: handle hidden points) - if (!c(s)) - return Facet(); - else - return tds().gather_full_cells(s, tp, out); + return tds().gather_full_cells(s, tp, out); } } From eb884bd4ebe51cc68024c316c0d0024a45a02c40 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 08:17:17 +0200 Subject: [PATCH 068/487] Removed a precondition This precondition may be false when processing the hidden cells of the regular triangulation --- Triangulation/include/CGAL/Triangulation_ds_vertex.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation_ds_vertex.h b/Triangulation/include/CGAL/Triangulation_ds_vertex.h index c2a056a2c6b..67552572038 100644 --- a/Triangulation/include/CGAL/Triangulation_ds_vertex.h +++ b/Triangulation/include/CGAL/Triangulation_ds_vertex.h @@ -61,7 +61,6 @@ public: /// Set 's' as an incident full_cell void set_full_cell(Full_cell_handle s) /* Concept */ { - CGAL_precondition( Full_cell_handle() != s ); full_cell_ = s; } From f1a7c45490c9e66dafab6a3d85826fed43efb7b2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 09:17:23 +0200 Subject: [PATCH 069/487] Hidden points are now handled during insertion and stored in a common container Note that they are not handled/restored during removal yet --- .../include/CGAL/Regular_triangulation.h | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index e1280f5e2a3..8899565664e 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -379,6 +379,49 @@ public: bool is_valid(bool verbose = false, int level = 0) const; +private: + + template + void + process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, + OutputIterator vertices_out) const + { + // Get all vertices + while(cz_begin != cz_end) + { + Full_cell_handle fch = *cz_begin; + for (int i = 0 ; i <= current_dimension() ; ++i) + { + Vertex_handle vh = fch->vertex(i); + if (vh->full_cell() != Full_cell_handle()) + { + (*vertices_out++) = vh; + vh->set_full_cell(Full_cell_handle()); + } + } + ++cz_begin; + } + } + + + template + void + process_cz_vertices_after_insertion(InputIterator vertices_begin, + InputIterator vertices_end) + { + // Get all vertices + while(vertices_begin != vertices_end) + { + Vertex_handle vh = *vertices_begin; + if (vh->full_cell() == Full_cell_handle()) + { + m_hidden_points.push_back(vh->point()); + tds().delete_vertex(vh); + } + ++vertices_begin; + } + } + private: // Some internal types to shorten notation using typename Base::Coaffine_orientation_d; @@ -823,7 +866,17 @@ Regular_triangulation cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); - return insert_in_hole(p, cs.begin(), cs.end(), ft); + + std::vector cz_vertices; + cz_vertices.reserve(64); + process_conflict_zone(cs.begin(), cs.end(), + std::back_inserter(cz_vertices)); + + Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft); + + process_cz_vertices_after_insertion(cz_vertices.begin(), cz_vertices.end()); + + return ret; } } From ded123507d0918ad9a6616cff4df24597f162157 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 09:19:44 +0200 Subject: [PATCH 070/487] Updated and new input data files for apps --- .../data/points_2 - extreme weights.cin | 11 +++++++ .../Triangulation/data/points_2.cin | 29 ++++++++++++------- .../data/points_3 - extreme weights.cin | 11 +++++++ .../data/points_3 - no weights.cin | 11 +++++++ .../Triangulation/data/points_3.cin | 8 ++--- .../Triangulation_2/data/points.cin | 29 ++++++++++++------- .../data/points - extreme weights.cin | 10 +++++++ .../data/points - no weights.cin | 10 +++++++ .../Triangulation_3/data/points.cin | 18 ++++++------ 9 files changed, 104 insertions(+), 33 deletions(-) create mode 100644 Triangulation/applications/Triangulation/data/points_2 - extreme weights.cin create mode 100644 Triangulation/applications/Triangulation/data/points_3 - extreme weights.cin create mode 100644 Triangulation/applications/Triangulation/data/points_3 - no weights.cin create mode 100644 Triangulation_3/applications/Triangulation_3/data/points - extreme weights.cin create mode 100644 Triangulation_3/applications/Triangulation_3/data/points - no weights.cin diff --git a/Triangulation/applications/Triangulation/data/points_2 - extreme weights.cin b/Triangulation/applications/Triangulation/data/points_2 - extreme weights.cin new file mode 100644 index 00000000000..19b563f4835 --- /dev/null +++ b/Triangulation/applications/Triangulation/data/points_2 - extreme weights.cin @@ -0,0 +1,11 @@ +2 +0.0071 1.6899 0 +0.3272 1.3694 0.05 +1.3697 1.8296 0.1 +0.6722 0.3012 0.15 +1.1726 0.1899 0.2 +0.4374 2.8541 100.25 +2.5923 0.1904 0.3 +1.3083 2.5462 200.35 +1.4981 1.3929 0.4 +2.1304 2.055 0.45 \ No newline at end of file diff --git a/Triangulation/applications/Triangulation/data/points_2.cin b/Triangulation/applications/Triangulation/data/points_2.cin index 5e75591106d..5a087138dcd 100644 --- a/Triangulation/applications/Triangulation/data/points_2.cin +++ b/Triangulation/applications/Triangulation/data/points_2.cin @@ -1,11 +1,20 @@ 2 -0.0071 1.6899 0 -0.3272 1.3694 0.05 -1.3697 1.8296 0.1 -0.6722 0.3012 0.15 -1.1726 0.1899 0.2 -0.4374 2.8541 0.25 -2.5923 0.1904 0.3 -1.3083 2.5462 0.35 -1.4981 1.3929 0.4 -2.1304 2.055 0.45 \ No newline at end of file +0 0 6.28953 +-2.85086 -0.471442 6.12896 +1.90972 0.101219 0.988689 +0.637771 2.59367 5.80372 +2.22209 0.903198 2.19478 +-0.487202 -2.71506 4.90996 +1.1193 -1.91787 2.99626 +1.54714 0.109831 0 +0.44556 -2.73047 4.48142 +0.427936 1.28495 6.23624 +-2.67212 0.766674 5.29623 +1.5763 -1.59828 2.58905 +-0.476603 2.2546 6.04797 +1.57172 -0.514711 6.11405 +1.84528 2.10139 5.53936 +-2.99827 -0.101677 5.92246 +-0.482122 -2.39584 4.44264 +-2.25558 -1.492 6.23448 +0.128475 -1.75125 3.18916 \ No newline at end of file diff --git a/Triangulation/applications/Triangulation/data/points_3 - extreme weights.cin b/Triangulation/applications/Triangulation/data/points_3 - extreme weights.cin new file mode 100644 index 00000000000..d1a088200f2 --- /dev/null +++ b/Triangulation/applications/Triangulation/data/points_3 - extreme weights.cin @@ -0,0 +1,11 @@ +3 +0.0071 1.6899 2.521 0 +0.3272 1.3694 3.15 0.05 +1.3697 1.8296 2.654 0.1 +-10.6722 0.3012 0.1548 1000.15 +1.1726 0.1899 0.3658 0.2 +0.4374 20.8541 1.45894 2000.25 +2.5923 0.1904 0.6971 0.3 +10.3083 2.5462 1.3658 1000.35 +1.4981 1.3929 2.949 0.4 +2.1304 2.055 0.6597455 1.45 \ No newline at end of file diff --git a/Triangulation/applications/Triangulation/data/points_3 - no weights.cin b/Triangulation/applications/Triangulation/data/points_3 - no weights.cin new file mode 100644 index 00000000000..58e5426c6a9 --- /dev/null +++ b/Triangulation/applications/Triangulation/data/points_3 - no weights.cin @@ -0,0 +1,11 @@ +3 +0.0071 1.6899 2.521 0 +0.3272 1.3694 3.15 0 +1.3697 1.8296 2.654 0 +-10.6722 0.3012 0.1548 0 +1.1726 0.1899 0.3658 0 +0.4374 20.8541 1.45894 0 +2.5923 0.1904 0.6971 0 +10.3083 2.5462 1.3658 0 +1.4981 1.3929 2.949 0 +2.1304 2.055 0.6597455 0 \ No newline at end of file diff --git a/Triangulation/applications/Triangulation/data/points_3.cin b/Triangulation/applications/Triangulation/data/points_3.cin index 6b094b18509..d1a088200f2 100644 --- a/Triangulation/applications/Triangulation/data/points_3.cin +++ b/Triangulation/applications/Triangulation/data/points_3.cin @@ -2,10 +2,10 @@ 0.0071 1.6899 2.521 0 0.3272 1.3694 3.15 0.05 1.3697 1.8296 2.654 0.1 -0.6722 0.3012 0.1548 0.15 +-10.6722 0.3012 0.1548 1000.15 1.1726 0.1899 0.3658 0.2 -0.4374 2.8541 1.45894 0.25 +0.4374 20.8541 1.45894 2000.25 2.5923 0.1904 0.6971 0.3 -1.3083 2.5462 1.3658 0.35 +10.3083 2.5462 1.3658 1000.35 1.4981 1.3929 2.949 0.4 -2.1304 2.055 0.6597455 0.45 \ No newline at end of file +2.1304 2.055 0.6597455 1.45 \ No newline at end of file diff --git a/Triangulation_2/applications/Triangulation_2/data/points.cin b/Triangulation_2/applications/Triangulation_2/data/points.cin index 52e8743d807..5e78e2349bc 100644 --- a/Triangulation_2/applications/Triangulation_2/data/points.cin +++ b/Triangulation_2/applications/Triangulation_2/data/points.cin @@ -1,10 +1,19 @@ -0.0071 1.6899 0 -0.3272 1.3694 0.05 -1.3697 1.8296 0.1 -0.6722 0.3012 0.15 -1.1726 0.1899 0.2 -0.4374 2.8541 0.25 -2.5923 0.1904 0.3 -1.3083 2.5462 0.35 -1.4981 1.3929 0.4 -2.1304 2.055 0.45 \ No newline at end of file +0 0 6.28953 +-2.85086 -0.471442 6.12896 +1.90972 0.101219 0.988689 +0.637771 2.59367 5.80372 +2.22209 0.903198 2.19478 +-0.487202 -2.71506 4.90996 +1.1193 -1.91787 2.99626 +1.54714 0.109831 0 +0.44556 -2.73047 4.48142 +0.427936 1.28495 6.23624 +-2.67212 0.766674 5.29623 +1.5763 -1.59828 2.58905 +-0.476603 2.2546 6.04797 +1.57172 -0.514711 6.11405 +1.84528 2.10139 5.53936 +-2.99827 -0.101677 5.92246 +-0.482122 -2.39584 4.44264 +-2.25558 -1.492 6.23448 +0.128475 -1.75125 3.18916 \ No newline at end of file diff --git a/Triangulation_3/applications/Triangulation_3/data/points - extreme weights.cin b/Triangulation_3/applications/Triangulation_3/data/points - extreme weights.cin new file mode 100644 index 00000000000..10c0791ad4c --- /dev/null +++ b/Triangulation_3/applications/Triangulation_3/data/points - extreme weights.cin @@ -0,0 +1,10 @@ +0.0071 1.6899 2.521 0 +0.3272 1.3694 3.15 0.05 +1.3697 1.8296 2.654 0.1 +-10.6722 0.3012 0.1548 1000.15 +1.1726 0.1899 0.3658 0.2 +0.4374 20.8541 1.45894 2000.25 +2.5923 0.1904 0.6971 0.3 +10.3083 2.5462 1.3658 1000.35 +1.4981 1.3929 2.949 0.4 +2.1304 2.055 0.6597455 1.45 \ No newline at end of file diff --git a/Triangulation_3/applications/Triangulation_3/data/points - no weights.cin b/Triangulation_3/applications/Triangulation_3/data/points - no weights.cin new file mode 100644 index 00000000000..9dcea4973dc --- /dev/null +++ b/Triangulation_3/applications/Triangulation_3/data/points - no weights.cin @@ -0,0 +1,10 @@ +0.0071 1.6899 2.521 0 +0.3272 1.3694 3.15 0 +1.3697 1.8296 2.654 0 +-10.6722 0.3012 0.1548 0 +1.1726 0.1899 0.3658 0 +0.4374 20.8541 1.45894 0 +2.5923 0.1904 0.6971 0 +10.3083 2.5462 1.3658 0 +1.4981 1.3929 2.949 0 +2.1304 2.055 0.6597455 0 \ No newline at end of file diff --git a/Triangulation_3/applications/Triangulation_3/data/points.cin b/Triangulation_3/applications/Triangulation_3/data/points.cin index 5f2f53d1426..9dcea4973dc 100644 --- a/Triangulation_3/applications/Triangulation_3/data/points.cin +++ b/Triangulation_3/applications/Triangulation_3/data/points.cin @@ -1,10 +1,10 @@ 0.0071 1.6899 2.521 0 -0.3272 1.3694 3.15 0.05 -1.3697 1.8296 2.654 0.1 -0.6722 0.3012 0.1548 0.15 -1.1726 0.1899 0.3658 0.2 -0.4374 2.8541 1.45894 0.25 -2.5923 0.1904 0.6971 0.3 -1.3083 2.5462 1.3658 0.35 -1.4981 1.3929 2.949 0.4 -2.1304 2.055 0.6597455 0.45 \ No newline at end of file +0.3272 1.3694 3.15 0 +1.3697 1.8296 2.654 0 +-10.6722 0.3012 0.1548 0 +1.1726 0.1899 0.3658 0 +0.4374 20.8541 1.45894 0 +2.5923 0.1904 0.6971 0 +10.3083 2.5462 1.3658 0 +1.4981 1.3929 2.949 0 +2.1304 2.055 0.6597455 0 \ No newline at end of file From b23f01ebf5f21d20f152ec41894a4a0f87ec73f7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 09:32:46 +0200 Subject: [PATCH 071/487] Oops: I removed a line that is still needed --- Tangential_complex/include/CGAL/Tangential_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3acc9a1e857..072482c53d2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -64,6 +64,7 @@ class Tangential_complex typedef typename Kernel::Vector_d Vector; typedef Tr Triangulation; + typedef typename Triangulation::Geom_traits Tr_traits; typedef typename Triangulation::Point Tr_point; typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; @@ -117,7 +118,7 @@ public: Triangulation(Intrinsic_dimension), Tr_vertex_handle())); Triangulation &local_tr = m_triangulations.back().first; - const Geom_traits &local_tr_traits = local_tr.geom_traits(); + const Tr_traits &local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations.back().second; // Estimate the tangent space From a8fce8b2fc0373ae33b825a4f8fde7ec7c19f27f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 12:43:47 +0200 Subject: [PATCH 072/487] Disable randomization + debugging code --- Tangential_complex/include/CGAL/Tangential_complex.h | 7 ++++--- .../test/Tangential_complex/test_tangential_complex.cpp | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 072482c53d2..432fda780b0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -148,14 +148,14 @@ public: } // Now we can insert the points - + // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(0, 0), CGAL::sqrt(max_squared_weight)); center_vertex = local_tr.insert(wp); center_vertex->data() = i; - std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; + //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; /*std::cerr << 0 << " " << 0 << " " @@ -179,6 +179,7 @@ public: Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); + //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) { /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " @@ -189,7 +190,7 @@ public: ++it_wp; } } - + // CJTODO DEBUG std::cerr << "\nChecking topology and geometry..." << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index d115652f41e..edc95702711 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -15,6 +15,7 @@ int main() #else const int NUM_POINTS = 500; #endif + CGAL::default_random = CGAL::Random(0); // NO RANDOM CGAL::Random_points_on_sphere_3 generator(3.0); std::vector points; points.reserve(NUM_POINTS); From 3d8bb299d201d55b0adb9e1d527dd0d7b0127a25 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 12:45:39 +0200 Subject: [PATCH 073/487] Fix insert_if_in_star --- .../include/CGAL/Regular_triangulation.h | 118 +++++++++--------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 8899565664e..9d54641ea32 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -264,7 +264,9 @@ public: } Vertex_handle insert_outside_affine_hull(const Weighted_point &); - Vertex_handle insert_in_conflicting_cell(const Weighted_point &, const Full_cell_handle); + Vertex_handle insert_in_conflicting_cell( + const Weighted_point &, const Full_cell_handle, + const Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle()); Vertex_handle insert_if_in_star(const Weighted_point &, const Vertex_handle, @@ -273,10 +275,6 @@ public: const Facet &, const Full_cell_handle); - Vertex_handle insert_in_conflicting_cell_if_in_star(const Weighted_point &, - const Vertex_handle, - const Full_cell_handle); - Vertex_handle insert_if_in_star( const Weighted_point & p, const Vertex_handle star_center, const Full_cell_handle start = Full_cell_handle()) @@ -381,6 +379,25 @@ public: private: + template + bool + does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end, + Vertex_handle vh) const + { + // Check all vertices + while(cz_begin != cz_end) + { + Full_cell_handle fch = *cz_begin; + for (int i = 0 ; i <= current_dimension() ; ++i) + { + if (fch->vertex(i) == vh) + return true; + } + ++cz_begin; + } + return false; + } + template void process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, @@ -843,43 +860,6 @@ Regular_triangulation return v; } -template< typename RTTraits, typename TDS > -typename Regular_triangulation::Vertex_handle -Regular_triangulation -::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s) -{ - typedef std::vector Full_cell_h_vector; - - Orientation_d ori = geom_traits().orientation_d_object(); - Power_test_d side = geom_traits().power_test_d_object(); - Conflict_pred_in_fullspace c(*this, p, ori, side); - // If p is not in conflict with s, then p is hidden - // => we don't insert it (CJTODO: handle hidden points) - if (!c(s)) - { - m_hidden_points.push_back(p); - return Vertex_handle(); - } - else - { - Full_cell_h_vector cs; // for storing conflicting full_cells. - cs.reserve(64); - std::back_insert_iterator out(cs); - Facet ft = compute_conflict_zone(p, s, out); - - std::vector cz_vertices; - cz_vertices.reserve(64); - process_conflict_zone(cs.begin(), cs.end(), - std::back_inserter(cz_vertices)); - - Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft); - - process_cz_vertices_after_insertion(cz_vertices.begin(), cz_vertices.end()); - - return ret; - } -} - template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation @@ -916,7 +896,7 @@ Regular_triangulation } } else - return insert_in_conflicting_cell_if_in_star(p, star_center, s); + return insert_in_conflicting_cell(p, s, star_center); break; } } @@ -927,23 +907,49 @@ Regular_triangulation template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation -::insert_in_conflicting_cell_if_in_star(const Weighted_point & p, - const Vertex_handle star_center, - const Full_cell_handle s) +::insert_in_conflicting_cell(const Weighted_point & p, + const Full_cell_handle s, + const Vertex_handle only_if_this_vertex_is_in_the_cz) { typedef std::vector Full_cell_h_vector; - static Full_cell_h_vector cs; // for storing conflicting full_cells. - cs.clear(); - // cs.reserve(64); - std::back_insert_iterator out(cs); - Facet ft = compute_conflict_zone(p, s, out); - Full_cell_h_vector::const_iterator it = cs.begin(), it_end = cs.end(); - for ( ; it != it_end ; ++it) + + Orientation_d ori = geom_traits().orientation_d_object(); + Power_test_d side = geom_traits().power_test_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + // If p is not in conflict with s, then p is hidden + // => we don't insert it (CJTODO: handle hidden points) + if (!c(s)) { - if ((*it)->has_vertex(star_center)) - return insert_in_hole(p, cs.begin(), cs.end(), ft); + m_hidden_points.push_back(p); + return Vertex_handle(); + } + else + { + Full_cell_h_vector cs; // for storing conflicting full_cells. + cs.reserve(64); + std::back_insert_iterator out(cs); + Facet ft = compute_conflict_zone(p, s, out); + + // Check if the CZ contains "only_if_this_vertex_is_in_the_cz" + if (only_if_this_vertex_is_in_the_cz != Vertex_handle() + && !does_cell_range_contain_vertex(cs.begin(), cs.end(), + only_if_this_vertex_is_in_the_cz)) + { + return Vertex_handle(); + } + + // Otherwise, proceed with the insertion + std::vector cz_vertices; + cz_vertices.reserve(64); + process_conflict_zone(cs.begin(), cs.end(), + std::back_inserter(cz_vertices)); + + Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft); + + process_cz_vertices_after_insertion(cz_vertices.begin(), cz_vertices.end()); + + return ret; } - return Vertex_handle(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES From 4b48d7db878da08a8c824672c9059e4379379db5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 16:03:08 +0200 Subject: [PATCH 074/487] Comments clean-up --- NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h | 4 ---- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- Triangulation/include/CGAL/Triangulation_data_structure.h | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h index 3a27eee90ff..62ad90afa9c 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h @@ -78,10 +78,6 @@ template struct Construct_flat_orientation : private Store_kernel // the points are affinely independent. template result_type operator()(Iter f, Iter e)const{ - /*std::cerr << "Kernel flat orientation - points: " ; // CJTODO DEBUG - for (Iter it = f ; it != e ; ++it) - std::cerr << (*it)[0] << " "; - std::cerr << std::endl; // CJTODO DEBUG*/ Iter f_save = f; PD pd (this->kernel()); CCC ccc (this->kernel()); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 9d54641ea32..d0552b6d7eb 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -917,7 +917,7 @@ Regular_triangulation Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); // If p is not in conflict with s, then p is hidden - // => we don't insert it (CJTODO: handle hidden points) + // => we don't insert it if (!c(s)) { m_hidden_points.push_back(p); diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index b89f1386821..3ff6235e985 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -1023,7 +1023,7 @@ Triangulation_data_structure Full_cell_handle inside = full_cell(rot); Full_cell_handle outside = neighbor(inside, index_of_covertex(rot)); // "m" is the vertex of outside which is not on the boundary - Vertex_handle m = inside->mirror_vertex(index_of_covertex(rot), current_dimension()); // CJTODO: use mirror_index? + Vertex_handle m = inside->mirror_vertex(index_of_covertex(rot), current_dimension()); // "index" is the index of m in "outside" int index = outside->index(m); // new_neighbor is the inside cell which is registered as the neighbor From a7082cd595c0a5e6b64aaed3c728ee46182ef7b3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 17:15:12 +0200 Subject: [PATCH 075/487] Parallel version --- .../include/CGAL/Tangential_complex.h | 264 +++++++++++------- .../test/Tangential_complex/CMakeLists.txt | 9 + .../test_tangential_complex.cpp | 23 +- 3 files changed, 186 insertions(+), 110 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 432fda780b0..ce7d5615f16 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,6 +23,7 @@ #define TANGENTIAL_COMPLEX_H #include +#include #include #include @@ -35,12 +36,17 @@ #include #include +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif + namespace CGAL { /// The class Tangential_complex represents a tangential complex template < typename Kernel, int Intrinsic_dimension, + typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Regular_triangulation < Regular_triangulation_euclidean_traits< @@ -59,23 +65,23 @@ template < > class Tangential_complex { - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Vector_d Vector; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; - typedef Tr Triangulation; - typedef typename Triangulation::Geom_traits Tr_traits; - typedef typename Triangulation::Point Tr_point; - typedef typename Triangulation::Bare_point Tr_bare_point; - typedef typename Triangulation::Vertex_handle Tr_vertex_handle; - typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; + typedef Tr Triangulation; + typedef typename Triangulation::Geom_traits Tr_traits; + typedef typename Triangulation::Point Tr_point; + typedef typename Triangulation::Bare_point Tr_bare_point; + typedef typename Triangulation::Vertex_handle Tr_vertex_handle; + typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; - typedef typename std::vector Tangent_space_base; + typedef typename std::vector Tangent_space_base; - typedef std::pair Tr_and_VH; - typedef typename std::vector Point_container; - typedef typename std::vector Tr_container; - typedef typename std::vector TS_container; + typedef std::pair Tr_and_VH; + typedef typename std::vector Point_container; + typedef typename std::vector Tr_container; + typedef typename std::vector TS_container; // Stores the index of the original Point in the ambient space /*struct Tr_point_with_index @@ -106,99 +112,26 @@ public: // We need to do that because we don't want the container to copy the // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations - m_triangulations.reserve(m_points.size()); - m_tangent_spaces.reserve(m_points.size()); - - Point_container::const_iterator it_p = m_points.begin(); - Point_container::const_iterator it_p_end = m_points.end(); - // For each point p in ambient space - for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) + m_triangulations.resize( + m_points.size(), + std::make_pair((Triangulation*)NULL, Tr_vertex_handle())); + m_tangent_spaces.resize(m_points.size()); + +#ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) { - m_triangulations.push_back(std::make_pair( - Triangulation(Intrinsic_dimension), - Tr_vertex_handle())); - Triangulation &local_tr = m_triangulations.back().first; - const Tr_traits &local_tr_traits = local_tr.geom_traits(); - Tr_vertex_handle ¢er_vertex = m_triangulations.back().second; - - // Estimate the tangent space - m_tangent_spaces.push_back(compute_tangent_space(*it_p)); - - //*************************************************** - // Build a minimal triangulation in the tangent space - // (we only need the star of p) - //*************************************************** - - // First, compute the projected points - std::vector projected_points; - FT max_squared_weight = 0; - projected_points.reserve(m_points.size() - 1); - Point_container::const_iterator it2_p = m_points.begin(); - for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) - { - // ith point = p, which is already inserted - if (j != i) - { - Tr_point wp = project_point(*it2_p, *it_p, m_tangent_spaces.back()); - projected_points.push_back(wp); - FT w = local_tr_traits.point_weight_d_object()(wp); - if (w > max_squared_weight) - max_squared_weight = w; - } - } - - // Now we can insert the points - - // Insert p - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(0, 0), - CGAL::sqrt(max_squared_weight)); - center_vertex = local_tr.insert(wp); - center_vertex->data() = i; - //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; - - /*std::cerr << 0 << " " - << 0 << " " - << CGAL::sqrt(max_squared_weight) << std::endl;*/ - - // Insert the other points - std::vector::const_iterator it_wp = projected_points.begin(); - it2_p = m_points.begin(); - for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) - { - // ith point = p, which is already inserted - if (j != i) - { - FT squared_dist_to_tangent_plane = - local_tr_traits.point_weight_d_object()(*it_wp); - FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.point_drop_weight_d_object()(*it_wp), - w); - /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); - Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ - - Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); - //Tr_vertex_handle vh = local_tr.insert(wp); - if (vh != Tr_vertex_handle()) - { - /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " - << traits.point_drop_weight_d_object()(*it_wp)[1] << " " - << w << std::endl;*/ - vh->data() = j; - } - ++it_wp; - } - } - - // CJTODO DEBUG - std::cerr << "\nChecking topology and geometry..." - << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); - // DEBUG: output the local mesh into an OFF file - //std::stringstream sstr; - //sstr << "data/local_tri_" << i << ".off"; - //std::ofstream off_stream_tr(sstr.str()); - //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); + // Apply moves in triangulation + tbb::parallel_for(tbb::blocked_range(0, m_points.size()), + Compute_tangent_triangulation(*this) + ); + } + // Sequential + else +#endif // CGAL_LINKED_WITH_TBB + { + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + compute_tangent_triangulation(i); } } @@ -244,7 +177,7 @@ public: // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { - const Triangulation &tr = it_tr->first; + const Triangulation &tr = *it_tr->first; Tr_vertex_handle center_vh = it_tr->second; std::vector incident_cells; @@ -273,6 +206,123 @@ public: } private: + +#ifdef CGAL_LINKED_WITH_TBB + // Functor for compute_tangential_complex function + class Compute_tangent_triangulation + { + Tangential_complex & m_tc; + + public: + // Constructor + Compute_tangent_triangulation(Tangential_complex &tc) + : m_tc(tc) + {} + + // Constructor + Compute_tangent_triangulation(const Compute_tangent_triangulation &ctt) + : m_tc(ctt.m_tc) + {} + + // operator() + void operator()( const tbb::blocked_range& r ) const + { + for( size_t i = r.begin() ; i != r.end() ; ++i) + m_tc.compute_tangent_triangulation(i); + } + }; +#endif // CGAL_LINKED_WITH_TBB + + void compute_tangent_triangulation(std::size_t i) + { + Triangulation *p_local_tr = + m_triangulations[i].first = + new Triangulation(Intrinsic_dimension); + const Tr_traits &local_tr_traits = p_local_tr->geom_traits(); + Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; + + // Estimate the tangent space + const Point ¢er_pt = m_points[i]; + m_tangent_spaces[i] = compute_tangent_space(center_pt); + + //*************************************************** + // Build a minimal triangulation in the tangent space + // (we only need the star of p) + //*************************************************** + + // First, compute the projected points + std::vector projected_points; + FT max_squared_weight = 0; + projected_points.reserve(m_points.size() - 1); + Point_container::const_iterator it_p = m_points.begin(); + Point_container::const_iterator it_p_end = m_points.end(); + for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) + { + // ith point = p, which is already inserted + if (j != i) + { + Tr_point wp = project_point(*it_p, center_pt, m_tangent_spaces[i]); + projected_points.push_back(wp); + FT w = local_tr_traits.point_weight_d_object()(wp); + if (w > max_squared_weight) + max_squared_weight = w; + } + } + + // Now we can insert the points + + // Insert p + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(0, 0), + CGAL::sqrt(max_squared_weight)); + center_vertex = p_local_tr->insert(wp); + center_vertex->data() = i; + //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; + + /*std::cerr << 0 << " " + << 0 << " " + << CGAL::sqrt(max_squared_weight) << std::endl;*/ + + // Insert the other points + std::vector::const_iterator it_wp = projected_points.begin(); + it_p = m_points.begin(); + for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) + { + // ith point = p, which is already inserted + if (j != i) + { + FT squared_dist_to_tangent_plane = + local_tr_traits.point_weight_d_object()(*it_wp); + FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.point_drop_weight_d_object()(*it_wp), + w); + /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); + Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ + + Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); + //Tr_vertex_handle vh = p_local_tr->insert(wp); + if (vh != Tr_vertex_handle()) + { + /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " + << traits.point_drop_weight_d_object()(*it_wp)[1] << " " + << w << std::endl;*/ + vh->data() = j; + } + ++it_wp; + } + } + + // CJTODO DEBUG + //std::cerr << "\nChecking topology and geometry..." + // << (p_local_tr->is_valid(true) ? "OK.\n" : "Error.\n"); + // DEBUG: output the local mesh into an OFF file + //std::stringstream sstr; + //sstr << "data/local_tri_" << i << ".off"; + //std::ofstream off_stream_tr(sstr.str()); + //CGAL::export_triangulation_to_off(off_stream_tr, *p_local_tr); + } + Tangent_space_base compute_tangent_space(const Point &p) const { Tangent_space_base ts; diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt index 7ba896e34c7..8d58f3631fe 100644 --- a/Tangential_complex/test/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -17,6 +17,15 @@ find_package(CGAL QUIET COMPONENTS Core ) if ( CGAL_FOUND ) include( ${CGAL_USE_FILE} ) + + find_package( TBB QUIET ) + + if( TBB_FOUND ) + include(${TBB_USE_FILE}) + list(APPEND CGAL_3RD_PARTY_LIBRARIES ${TBB_LIBRARIES}) + endif() + + include( CGAL_CreateSingleSourceCGALProgram ) find_package(Eigen3 3.1.0) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index edc95702711..2fd7fe8a1c1 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -1,19 +1,33 @@ +// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB +// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/) +#ifdef _DEBUG +# define TBB_USE_THREADING_TOOL +#endif + #include #include #include #include +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif + int main() { typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; + +#ifdef CGAL_LINKED_WITH_TBB + tbb::task_scheduler_init init(10); +#endif #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 500; + const int NUM_POINTS = 5000; #endif CGAL::default_random = CGAL::Random(0); // NO RANDOM CGAL::Random_points_on_sphere_3 generator(3.0); @@ -25,8 +39,11 @@ int main() //points.push_back(Point((double)(rand()%10000)/5000, (double)(rand()%10000)/5000, 0.)); // CJTODO : plane } - CGAL::Tangential_complex tc( - points.begin(), points.end()); + CGAL::Tangential_complex< + Kernel, + INTRINSIC_DIMENSION, + CGAL::Parallel_tag> tc(points.begin(), points.end()); + tc.compute_tangential_complex(); std::stringstream output_filename; From a2e172c57eb9e2ef76164df111f34da3be42b9fd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 8 Sep 2014 06:47:17 +0200 Subject: [PATCH 076/487] Add a TODO --- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 9d54641ea32..4398424d330 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -1029,7 +1029,7 @@ Regular_triangulation } else { - Orientation_d ori = geom_traits().orientation_d_object(); + Orientation_d ori = geom_traits().orientation_d_object(); // CJTODO: create member variables for this? Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); return c(s); From 7b807794c9e72060686b860ac2f0d81d9b917c91 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 9 Sep 2014 10:24:46 +0200 Subject: [PATCH 077/487] Renamed "base" => "basis" --- Tangential_complex/include/CGAL/Tangential_complex.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ce7d5615f16..146f6990f17 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -76,12 +76,12 @@ class Tangential_complex typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; - typedef typename std::vector Tangent_space_base; + typedef typename std::vector Tangent_space_basis; typedef std::pair Tr_and_VH; typedef typename std::vector Point_container; typedef typename std::vector Tr_container; - typedef typename std::vector TS_container; + typedef typename std::vector TS_container; // Stores the index of the original Point in the ambient space /*struct Tr_point_with_index @@ -323,9 +323,9 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, *p_local_tr); } - Tangent_space_base compute_tangent_space(const Point &p) const + Tangent_space_basis compute_tangent_space(const Point &p) const { - Tangent_space_base ts; + Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); // CJTODO: this is only for a sphere in R^3 Vector t1(-p[1] - p[2], p[0], p[0]); @@ -362,7 +362,7 @@ private: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p Tr_point project_point(const Point &p, const Point &origin, - const Tangent_space_base &ts) const + const Tangent_space_basis &ts) const { Get_functor::type inner_pdct(m_k); Get_functor::type diff_points(m_k); From 2e80d4aa471e33d79ad4e2be521c624321adabcf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 9 Sep 2014 15:54:37 +0200 Subject: [PATCH 078/487] Add Gram-Schmidt algorithm + profiling + config file + simpler code thanks to new kernel features --- .../include/CGAL/Tangential_complex.h | 73 ++++++++++++------ .../include/CGAL/Tangential_complex/config.h | 28 +++++++ .../CGAL/Tangential_complex/utilities.h | 76 +++++++++++++++++++ 3 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/config.h create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/utilities.h diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 146f6990f17..667035a8940 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -22,12 +22,17 @@ #ifndef TANGENTIAL_COMPLEX_H #define TANGENTIAL_COMPLEX_H +#include + #include #include #include #include #include +#include + +#include #include // CJTODO TEMP @@ -41,6 +46,8 @@ #endif namespace CGAL { + +using namespace Tangential_complex_; /// The class Tangential_complex represents a tangential complex template < @@ -109,6 +116,10 @@ public: void compute_tangential_complex() { +#ifdef CGAL_TC_PROFILING + WallClockTimer t; +#endif + // We need to do that because we don't want the container to copy the // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations @@ -133,6 +144,11 @@ public: for (std::size_t i = 0 ; i < m_points.size() ; ++i) compute_tangent_triangulation(i); } + +#ifdef CGAL_TC_PROFILING + std::cerr << "Tangential complex computed in " << t.elapsed() + << " seconds." << std::endl; +#endif } std::ostream &export_to_off(std::ostream & os) @@ -291,6 +307,15 @@ private: // ith point = p, which is already inserted if (j != i) { + // CJTODO TEMP: for test only + /*if (local_tr_traits.squared_distance_d_object()( + local_tr_traits.point_drop_weight_d_object()(wp), + local_tr_traits.point_drop_weight_d_object()(*it_wp)) > 1) + { + ++it_wp; + continue; + }*/ + FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(*it_wp); FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); @@ -325,38 +350,40 @@ private: Tangent_space_basis compute_tangent_space(const Point &p) const { - Tangent_space_basis ts; - ts.reserve(Intrinsic_dimension); + + Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + //Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); + //Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); + Get_functor::type inner_pdct(m_k); // CJTODO TEMP + Get_functor::type diff_vec(m_k); + // CJTODO: this is only for a sphere in R^3 Vector t1(-p[1] - p[2], p[0], p[0]); Vector t2(p[1] * t1[2] - p[2] * t1[1], p[2] * t1[0] - p[0] * t1[2], p[0] * t1[1] - p[1] * t1[0]); - // CJTODO: this is for a plane (test) - //Vector t1(1, 0, 0); - //Vector t2(0, 1, 0); - + // Normalize t1 and t2 - Get_functor::type sqlen(m_k); + Get_functor::type scale(m_k); - // CJTODO: use this when Scaled_vector is fixed - //Get_functor::type scale(m_k); - //ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); - //ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); - - // ****** Temporary code ******* - FT t1_len = CGAL::sqrt(sqlen(t1)); - FT t2_len = CGAL::sqrt(sqlen(t2)); - for (int i = 0 ; i < Ambient_dimension::value ; ++i) - { - t1[i] /= t1_len; - t2[i] /= t2_len; - } - ts.push_back(t1); - ts.push_back(t2); - // ****** /Temporary code ******* + Tangent_space_basis ts; + ts.reserve(Intrinsic_dimension); + ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); + ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); return ts; + + // Alternative code (to be used later) + //Vector n = m_k.point_to_vector_d_object()(p); + //n = scaled_vec(n, 1./sqrt(sqlen(n))); + //Vector t1(12., 15., 65.); + //Vector t2(32., 5., 85.); + //Tangent_space_basis ts; + //ts.reserve(Intrinsic_dimension); + //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); + //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); + //return compute_gram_schmidt_basis(ts, m_k); } // Project the point in the tangent space diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h new file mode 100644 index 00000000000..1527b4ea3c8 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -0,0 +1,28 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin + +#ifndef CGAL_TC_CONFIG_H +#define CGAL_TC_CONFIG_H + +#include + +#define CGAL_TC_PROFILING + +#endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h new file mode 100644 index 00000000000..2ce238cc8c1 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -0,0 +1,76 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin + +#ifndef CGAL_TC_UTILITIES_H +#define CGAL_TC_UTILITIES_H + +#include +#include + +#include + +namespace CGAL { + +namespace Tangential_complex_ { + + template + std::vector + compute_gram_schmidt_basis( + std::vector const& input_basis, + K const& kernel) + { + typedef typename K::Vector_d Vector; + typedef std::vector Basis; + const int D = Ambient_dimension::value; + + // Kernel functors + K::Squared_length_d sqlen = kernel.squared_length_d_object(); + K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); + //K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); + //K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); + Get_functor::type inner_pdct(kernel); // CJTODO TEMP + Get_functor::type diff_vec(kernel); + + Basis output_basis; + + Basis::const_iterator inb_it = input_basis.begin(); + Basis::const_iterator inb_it_end = input_basis.end(); + for (int i = 0 ; inb_it != inb_it_end ; ++inb_it, ++i) + { + Vector u = *inb_it; + + Basis::iterator outb_it = output_basis.begin(); + for (int j = 0 ; j < i ; ++j) + { + Vector const& ej = *outb_it; + Vector u_proj = scaled_vec(ej, inner_pdct(u, ej)); + u = diff_vec(u, u_proj); + } + + output_basis.push_back(scaled_vec(u, 1./CGAL::sqrt(sqlen(u)))); + } + + return output_basis; + } + +}; // namespace Tangential_complex_ +} //namespace CGAL + +#endif // CGAL_TC_UTILITIES_H From 47a262697e9bc72d4683270b19e02081ef35fffb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 14:07:35 +0200 Subject: [PATCH 079/487] Eigen-based PCA to estimate tangent plane --- .../include/CGAL/Tangential_complex.h | 65 ++++++++++++++++++- .../include/CGAL/Tangential_complex/config.h | 2 + 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 667035a8940..f2f6735afd7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -36,6 +36,9 @@ #include // CJTODO TEMP +#include +#include + #include #include #include @@ -223,6 +226,23 @@ public: private: + class Compare_distance_to_ref_point + { + public: + Compare_distance_to_ref_point(Point const& ref, Kernel const& k) + : m_ref(ref), m_k(k) {} + + bool operator()(Point const& p1, Point const& p2) + { + Kernel::Squared_distance_d sqdist = m_k.squared_distance_d_object(); + return sqdist(p1, m_ref) < sqdist(p2, m_ref); + } + + private: + Point const& m_ref; + Kernel const& m_k; + }; + #ifdef CGAL_LINKED_WITH_TBB // Functor for compute_tangential_complex function class Compute_tangent_triangulation @@ -350,7 +370,8 @@ private: Tangent_space_basis compute_tangent_space(const Point &p) const { - + // Kernel functors + Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); //Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); @@ -358,6 +379,47 @@ private: Get_functor::type inner_pdct(m_k); // CJTODO TEMP Get_functor::type diff_vec(m_k); + // CJTODO: do better than that (ANN?) + typedef std::set Sorted_points; + Sorted_points sorted_points( + Compare_distance_to_ref_point(p, m_k)); + sorted_points.insert(m_points.begin(), m_points.end()); + + //******************************* PCA ************************************* + + const int amb_dim = Ambient_dimension::value; + Eigen::MatrixXd mat(NUM_POINTS_FOR_PCA, amb_dim); + int j = 0; + for (Sorted_points::const_iterator it = sorted_points.begin() ; + j < NUM_POINTS_FOR_PCA ; ++it, ++j) + { + for (int i = 0 ; i < amb_dim ; ++i) + mat(j, i) = (*it)[i]; + } + Eigen::MatrixXd centered = mat.rowwise() - mat.colwise().mean(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver eig(cov); + + // The eigenvectors are sorted in increasing order of their corresponding + // eigenvalues + Tangent_space_basis ts; + for (int i = amb_dim - 1 ; i >= amb_dim - Intrinsic_dimension ; --i) + { + ts.push_back(constr_vec( + amb_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + amb_dim)); + } + + //************************************************************************* + + //Vector n = m_k.point_to_vector_d_object()(p); + //n = scaled_vec(n, 1./sqrt(sqlen(n))); + //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; + + return compute_gram_schmidt_basis(ts, m_k); + + /* // CJTODO: this is only for a sphere in R^3 Vector t1(-p[1] - p[2], p[0], p[0]); Vector t2(p[1] * t1[2] - p[2] * t1[1], @@ -384,6 +446,7 @@ private: //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); //return compute_gram_schmidt_basis(ts, m_k); + */ } // Project the point in the tangent space diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 1527b4ea3c8..a05abf81622 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -25,4 +25,6 @@ #define CGAL_TC_PROFILING +const std::size_t NUM_POINTS_FOR_PCA = 30; + #endif // CGAL_TC_CONFIG_H From d37b81a25e66f6680bbc374e0fd645f46d8e33c8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 14:29:34 +0200 Subject: [PATCH 080/487] Comments clean-up --- .../include/CGAL/Tangential_complex.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f2f6735afd7..7572d4b19d8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -315,10 +315,6 @@ private: center_vertex->data() = i; //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; - /*std::cerr << 0 << " " - << 0 << " " - << CGAL::sqrt(max_squared_weight) << std::endl;*/ - // Insert the other points std::vector::const_iterator it_wp = projected_points.begin(); it_p = m_points.begin(); @@ -342,16 +338,11 @@ private: Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.point_drop_weight_d_object()(*it_wp), w); - /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); - Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); //Tr_vertex_handle vh = p_local_tr->insert(wp); if (vh != Tr_vertex_handle()) { - /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " - << traits.point_drop_weight_d_object()(*it_wp)[1] << " " - << w << std::endl;*/ vh->data() = j; } ++it_wp; @@ -388,15 +379,16 @@ private: //******************************* PCA ************************************* const int amb_dim = Ambient_dimension::value; - Eigen::MatrixXd mat(NUM_POINTS_FOR_PCA, amb_dim); + // One row = one point + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); int j = 0; for (Sorted_points::const_iterator it = sorted_points.begin() ; j < NUM_POINTS_FOR_PCA ; ++it, ++j) { for (int i = 0 ; i < amb_dim ; ++i) - mat(j, i) = (*it)[i]; + mat_points(j, i) = (*it)[i]; } - Eigen::MatrixXd centered = mat.rowwise() - mat.colwise().mean(); + Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; Eigen::SelfAdjointEigenSolver eig(cov); From 4015d0e1700e38fa0f779c6fccac69f6306f2301 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:00:09 +0200 Subject: [PATCH 081/487] Optimization to reduce the number of vertices we insert in the local triang While building the local triangulation, we keep the radius of the sphere centered at "center_vertex" and which contains all the circumspheres of the star of "center_vertex" For now, we use non-weighted circumspheres but it could be optimized by using weighted circumspheres (which are smaller) --- .../include/CGAL/Tangential_complex.h | 83 ++++++++++++++++++- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7572d4b19d8..f7324d2fb22 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -39,10 +39,13 @@ #include #include +#include + #include #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -243,6 +246,26 @@ private: Kernel const& m_k; }; + + struct Tr_vertex_to_bare_point + { + typedef typename Tr_vertex_handle argument_type; + typedef typename Tr_bare_point result_type; + + Tr_vertex_to_bare_point(Tr_traits const& traits) + : m_traits(traits) {} + + result_type operator()(argument_type const& vh) const + { + typename Tr_traits::Point_drop_weight_d pdw = + m_traits.point_drop_weight_d_object(); + return pdw(vh->point()); + } + + private: + Tr_traits const& m_traits; + }; + #ifdef CGAL_LINKED_WITH_TBB // Functor for compute_tangential_complex function class Compute_tangent_triangulation @@ -271,12 +294,21 @@ private: void compute_tangent_triangulation(std::size_t i) { + //std::cerr << "***********************************************" << std::endl; Triangulation *p_local_tr = m_triangulations[i].first = new Triangulation(Intrinsic_dimension); const Tr_traits &local_tr_traits = p_local_tr->geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; + // Traits functor & objects + Tr_traits::Center_of_sphere_d center_of_sphere = + local_tr_traits.center_of_sphere_d_object(); + Tr_traits::Squared_distance_d sqdist = + local_tr_traits.squared_distance_d_object(); + Tr_traits::Point_drop_weight_d drop_w = + local_tr_traits.point_drop_weight_d_object(); + // Estimate the tangent space const Point ¢er_pt = m_points[i]; m_tangent_spaces[i] = compute_tangent_space(center_pt); @@ -314,7 +346,13 @@ private: center_vertex = p_local_tr->insert(wp); center_vertex->data() = i; //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; - + + // While building the local triangulation, we keep the radius + // of the sphere centered at "center_vertex" and which contains all the + // circumspheres of the star of "center_vertex" + // For now, we use non-weighted circumspheres but it could be + // optimized by using weighted circumspheres (which are smaller) + FT star_sphere_squared_radius = std::numeric_limits::max(); // Insert the other points std::vector::const_iterator it_wp = projected_points.begin(); it_p = m_points.begin(); @@ -325,18 +363,25 @@ private: { // CJTODO TEMP: for test only /*if (local_tr_traits.squared_distance_d_object()( - local_tr_traits.point_drop_weight_d_object()(wp), - local_tr_traits.point_drop_weight_d_object()(*it_wp)) > 1) + drop_w(wp), + drop_w(*it_wp)) > 1) { ++it_wp; continue; }*/ + if (local_tr_traits.squared_distance_d_object()( + drop_w(wp), drop_w(*it_wp)) + > star_sphere_squared_radius) + { + ++it_wp; + continue; + } FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(*it_wp); FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.point_drop_weight_d_object()(*it_wp), + drop_w(*it_wp), w); Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); @@ -344,7 +389,37 @@ private: if (vh != Tr_vertex_handle()) { vh->data() = j; + + // Let's recompute star_sphere_squared_radius + if (p_local_tr->current_dimension() >= Intrinsic_dimension) + { + star_sphere_squared_radius = 0.; + // Get the incident cells and look for the biggest circumsphere + std::vector incident_cells; + p_local_tr->incident_full_cells( + center_vertex, + std::back_inserter(incident_cells)); + for (auto cell : incident_cells) // CJTODO C++11 + { + if (p_local_tr->is_infinite(cell)) + { + star_sphere_squared_radius = std::numeric_limits::max(); + break; + } + else + { + Tr_vertex_to_bare_point v2p(local_tr_traits); + Tr_bare_point c = center_of_sphere( + boost::make_transform_iterator(cell->vertices_begin(), v2p), + boost::make_transform_iterator(cell->vertices_end(), v2p)); + FT sq_circumdiam = 4.*sqdist(c, drop_w(center_vertex->point())); + if (sq_circumdiam > star_sphere_squared_radius) + star_sphere_squared_radius = sq_circumdiam; + } + } + } } + //std::cerr << star_sphere_squared_radius << std::endl; ++it_wp; } } From 38dc351ad3b567e71af252d8f547c77aa9a0680b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:07:32 +0200 Subject: [PATCH 082/487] Minor changes to the test (number of threads, random points...) --- .../test/Tangential_complex/test_tangential_complex.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 2fd7fe8a1c1..367a4b7b4e4 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -21,7 +21,11 @@ int main() const int INTRINSIC_DIMENSION = 2; #ifdef CGAL_LINKED_WITH_TBB +# ifdef _DEBUG + tbb::task_scheduler_init init(1); +# else tbb::task_scheduler_init init(10); +# endif #endif #ifdef _DEBUG @@ -29,7 +33,7 @@ int main() #else const int NUM_POINTS = 5000; #endif - CGAL::default_random = CGAL::Random(0); // NO RANDOM + //CGAL::default_random = CGAL::Random(0); // NO RANDOM CGAL::Random_points_on_sphere_3 generator(3.0); std::vector points; points.reserve(NUM_POINTS); From 9e4e2d255b27f065cd420e9ce4fca4b2a337ec1d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:17:31 +0200 Subject: [PATCH 083/487] Remove some "Get_functor" --- Tangential_complex/include/CGAL/Tangential_complex.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f7324d2fb22..7c7df9495d1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -440,10 +440,8 @@ private: Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - //Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - //Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - Get_functor::type inner_pdct(m_k); // CJTODO TEMP - Get_functor::type diff_vec(m_k); + Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); + Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); // CJTODO: do better than that (ANN?) typedef std::set Sorted_points; @@ -494,7 +492,7 @@ private: p[0] * t1[1] - p[1] * t1[0]); // Normalize t1 and t2 - Get_functor::type scale(m_k); + Kernel::Scaled_vector_d scale = m_k.scaled_vector_d_object(); Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); @@ -521,7 +519,8 @@ private: Tr_point project_point(const Point &p, const Point &origin, const Tangent_space_basis &ts) const { - Get_functor::type inner_pdct(m_k); + Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); + //Kernel::Difference_of_points_d diff_points= m_k.difference_of_points_d_object(); // CJTODO: use that Get_functor::type diff_points(m_k); std::vector coords; From 0138db9500d4325bf2f39581fdccf7889ab0e023 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:40:08 +0200 Subject: [PATCH 084/487] Restructure the test --- .../test_tangential_complex.cpp | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 367a4b7b4e4..d81a5c0af10 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -14,12 +14,31 @@ # include #endif +#ifdef _DEBUG + const int NUM_POINTS = 50; +#else + const int NUM_POINTS = 5000; +#endif + +template +std::vector generate_points_on_sphere(double radius) +{ + CGAL::Random_points_on_sphere_3 generator(radius); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + points.push_back(*generator++); + return points; +} + int main() { typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; - + + //CGAL::default_random = CGAL::Random(0); // NO RANDOM + #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG tbb::task_scheduler_init init(1); @@ -28,20 +47,7 @@ int main() # endif #endif -#ifdef _DEBUG - const int NUM_POINTS = 50; -#else - const int NUM_POINTS = 5000; -#endif - //CGAL::default_random = CGAL::Random(0); // NO RANDOM - CGAL::Random_points_on_sphere_3 generator(3.0); - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - { - points.push_back(*generator++); - //points.push_back(Point((double)(rand()%10000)/5000, (double)(rand()%10000)/5000, 0.)); // CJTODO : plane - } + std::vector points = generate_points_on_sphere(3.0); CGAL::Tangential_complex< Kernel, From 87c0716689e012e4319d33c53e823d72869c7629 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:40:32 +0200 Subject: [PATCH 085/487] Clean-up --- Tangential_complex/include/CGAL/Tangential_complex.h | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7c7df9495d1..91bda16a752 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -350,7 +350,7 @@ private: // While building the local triangulation, we keep the radius // of the sphere centered at "center_vertex" and which contains all the // circumspheres of the star of "center_vertex" - // For now, we use non-weighted circumspheres but it could be + // [TODO?] For now, we use non-weighted circumspheres but it could be // optimized by using weighted circumspheres (which are smaller) FT star_sphere_squared_radius = std::numeric_limits::max(); // Insert the other points @@ -361,14 +361,6 @@ private: // ith point = p, which is already inserted if (j != i) { - // CJTODO TEMP: for test only - /*if (local_tr_traits.squared_distance_d_object()( - drop_w(wp), - drop_w(*it_wp)) > 1) - { - ++it_wp; - continue; - }*/ if (local_tr_traits.squared_distance_d_object()( drop_w(wp), drop_w(*it_wp)) > star_sphere_squared_radius) @@ -522,7 +514,7 @@ private: Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); //Kernel::Difference_of_points_d diff_points= m_k.difference_of_points_d_object(); // CJTODO: use that Get_functor::type diff_points(m_k); - + std::vector coords; // Ambiant-space coords of the projected point std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); From 819c46a3d2fb5b830804859c9c9b3f908c736b52 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 17:14:29 +0200 Subject: [PATCH 086/487] Enable export_to_off when ambient dim > 3 (truncated points) --- .../include/CGAL/Tangential_complex.h | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 91bda16a752..f4caaddc5de 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -160,17 +160,31 @@ public: std::ostream &export_to_off(std::ostream & os) { const int ambient_dim = Ambient_dimension::value; - if (ambient_dim < 2 || ambient_dim > 3) + if (ambient_dim < 2) { - std::cerr << "Error: export_to_off => ambient dimension should be 2 or 3."; - os << "Error: export_to_off => ambient dimension should be 2 or 3."; + std::cerr << "Error: export_to_off => ambient dimension should be >= 2." + << std::endl; + os << "Error: export_to_off => ambient dimension should be >= 2." + << std::endl; return os; } + if (ambient_dim > 3) + { + std::cerr << "Warning: export_to_off => ambient dimension should be " + "<= 3. Only the first 3 coordinates will be exported." + << std::endl; + } + + int num_coords = min(ambient_dim, 3); if (Intrinsic_dimension < 1 || Intrinsic_dimension > 3) { - std::cerr << "Error: export_to_off => intrinsic dimension should be between 1 and 3."; - os << "Error: export_to_off => intrinsic dimension should be between 1 and 3."; + std::cerr << "Error: export_to_off => intrinsic dimension should be " + "between 1 and 3." + << std::endl; + os << "Error: export_to_off => intrinsic dimension should be " + "between 1 and 3." + << std::endl; return os; } @@ -184,7 +198,7 @@ public: for ( ; it_p != it_p_end ; ++it_p) { int i = 0; - for ( ; i < ambient_dim ; ++i) + for ( ; i < num_coords ; ++i) output << (*it_p)[i] << " "; if (i == 2) output << "0"; From 2f1c84e171a16985747e20a10cba20980e702eb9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 17:18:31 +0200 Subject: [PATCH 087/487] Let's give the Klein Bottle a try... --- .../test_tangential_complex.cpp | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index d81a5c0af10..e608e0159e7 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -7,8 +7,13 @@ #include #include #include +#include +#include #include +#include + +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -31,11 +36,36 @@ std::vector generate_points_on_sphere(double radius) return points; } +// a = big radius, b = small radius +template +std::vector generate_points_on_klein_bottle(double a, double b) +{ + typedef CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u = rng.get_double(0, 6.2832); + FT v = rng.get_double(0, 6.2832); + points.push_back(Kernel().construct_point_d_object()( + (a + b*cos(v))*cos(u), + (a + b*cos(v))*sin(u), + b*sin(v)*cos(u/2), + b*sin(v)*sin(u/2))); + } + return points; +} + int main() { - typedef CGAL::Epick_d > Kernel; - typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; + const int AMBIENT_DIMENSION = 4; + + typedef CGAL::Epick_d > Kernel; + typedef Kernel::Point_d Point; //CGAL::default_random = CGAL::Random(0); // NO RANDOM @@ -47,7 +77,8 @@ int main() # endif #endif - std::vector points = generate_points_on_sphere(3.0); + //std::vector points = generate_points_on_sphere(3.0); + std::vector points = generate_points_on_klein_bottle(4., 3.); CGAL::Tangential_complex< Kernel, From 43ad54314384ba61351865ed987819071fb04a9b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 17:30:27 +0200 Subject: [PATCH 088/487] Improve test --- .../test/Tangential_complex/test_tangential_complex.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index e608e0159e7..51f77c0814b 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -64,8 +64,8 @@ int main() const int INTRINSIC_DIMENSION = 2; const int AMBIENT_DIMENSION = 4; - typedef CGAL::Epick_d > Kernel; - typedef Kernel::Point_d Point; + typedef CGAL::Epick_d > Kernel; + typedef Kernel::Point_d Point; //CGAL::default_random = CGAL::Random(0); // NO RANDOM @@ -88,7 +88,8 @@ int main() tc.compute_tangential_complex(); std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << ".off"; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << + << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); tc.export_to_off(off_stream); From ea61acdb4c1d8a04e2bf4bcd96c0799a381a1e73 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 11 Sep 2014 09:54:57 +0200 Subject: [PATCH 089/487] Remove useless header + compilation fix --- .../test/Tangential_complex/test_tangential_complex.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 51f77c0814b..a44ed2fe252 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -13,8 +13,6 @@ #include #include -#include - #ifdef CGAL_LINKED_WITH_TBB # include #endif @@ -40,7 +38,7 @@ std::vector generate_points_on_sphere(double radius) template std::vector generate_points_on_klein_bottle(double a, double b) { - typedef CGAL::Kernel_traits::type Kernel; + typedef typename CGAL::Kernel_traits::type Kernel; typedef typename Kernel::FT FT; CGAL::Random rng; @@ -88,7 +86,7 @@ int main() tc.compute_tangential_complex(); std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); tc.export_to_off(off_stream); From a84f6908d0eab93e4d9a77734b3a01bc075eb405 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 11 Sep 2014 13:10:50 +0200 Subject: [PATCH 090/487] Use Nanoflann to help computing the tangent plane (using PCA) --- .../include/CGAL/Tangential_complex.h | 56 +- .../CGAL/Tangential_complex/Point_cloud.h | 349 ++++ .../CGAL/Tangential_complex/nanoflann.hpp | 1449 +++++++++++++++++ .../CGAL/Tangential_complex/utilities.h | 4 +- 4 files changed, 1837 insertions(+), 21 deletions(-) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/nanoflann.hpp diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f4caaddc5de..f2ee98ccef8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -26,11 +26,13 @@ #include #include +#include #include #include #include #include +#include #include @@ -90,11 +92,13 @@ class Tangential_complex typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename std::vector Tangent_space_basis; + + typedef Point_cloud Points; + typedef Point_cloud_data_structure Points_ds; typedef std::pair Tr_and_VH; - typedef typename std::vector Point_container; typedef typename std::vector Tr_container; - typedef typename std::vector TS_container; + typedef typename std::vector TS_container; // Stores the index of the original Point in the ambient space /*struct Tr_point_with_index @@ -115,7 +119,7 @@ public: template Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), m_points(first, last) {} + : m_k(k), m_points(first, last, k), m_points_ds(m_points, k) {} /// Destructor ~Tangential_complex() {} @@ -192,8 +196,8 @@ public: //******** VERTICES ************ - Point_container::const_iterator it_p = m_points.begin(); - Point_container::const_iterator it_p_end = m_points.end(); + Points::const_iterator it_p = m_points.begin(); + Points::const_iterator it_p_end = m_points.end(); // For each point p for ( ; it_p != it_p_end ; ++it_p) { @@ -260,7 +264,23 @@ private: Kernel const& m_k; }; - + struct Tr_vertex_to_global_point + { + typedef typename Tr_vertex_handle argument_type; + typedef typename Point result_type; + + Tr_vertex_to_global_point(Points const& points) + : m_points(points) {} + + result_type operator()(argument_type const& vh) const + { + return m_points[vh->data()]; + } + + private: + Points const& m_points; + }; + struct Tr_vertex_to_bare_point { typedef typename Tr_vertex_handle argument_type; @@ -336,8 +356,8 @@ private: std::vector projected_points; FT max_squared_weight = 0; projected_points.reserve(m_points.size() - 1); - Point_container::const_iterator it_p = m_points.begin(); - Point_container::const_iterator it_p_end = m_points.end(); + Points::const_iterator it_p = m_points.begin(); + Points::const_iterator it_p_end = m_points.end(); for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) { // ith point = p, which is already inserted @@ -449,23 +469,20 @@ private: Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - // CJTODO: do better than that (ANN?) - typedef std::set Sorted_points; - Sorted_points sorted_points( - Compare_distance_to_ref_point(p, m_k)); - sorted_points.insert(m_points.begin(), m_points.end()); + std::size_t neighbor_indices[NUM_POINTS_FOR_PCA]; + FT squared_distance[NUM_POINTS_FOR_PCA]; + m_points_ds.query_ANN( + p, NUM_POINTS_FOR_PCA, neighbor_indices, squared_distance); //******************************* PCA ************************************* const int amb_dim = Ambient_dimension::value; // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); - int j = 0; - for (Sorted_points::const_iterator it = sorted_points.begin() ; - j < NUM_POINTS_FOR_PCA ; ++it, ++j) + for (int j = 0 ; j < NUM_POINTS_FOR_PCA ; ++j) { for (int i = 0 ; i < amb_dim ; ++i) - mat_points(j, i) = (*it)[i]; + mat_points(j, i) = m_points[neighbor_indices[j]][i]; // CJTODO: Use kernel functor } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -531,7 +548,7 @@ private: std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); + std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); // CJTODO: use kernel functors? coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { @@ -554,7 +571,8 @@ private: private: const Kernel m_k; - Point_container m_points; + Points m_points; + Points_ds m_points_ds; TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations // and their center vertex diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h new file mode 100644 index 00000000000..1a130113f7e --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -0,0 +1,349 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin + +#ifndef POINT_CLOUD_H +#define POINT_CLOUD_H + +#include +#include +#include +#include + +#include "nanoflann.hpp" + +#include +#include +#include + +namespace CGAL { +namespace Tangential_complex_ { + +template +class Point_cloud +: public std::vector +{ +public: + typedef std::vector Base; + typedef Base Raw_container; + typedef Point_ Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + //typedef typename Base::iterator iterator; + //typedef typename Base::const_iterator const_iterator; + + static const int AMB_DIM = Ambient_dimension::value; + + Point_cloud(Kernel const& k) + : m_k(k) + { + m_mins.fill(std::numeric_limits::max()); + m_maxs.fill(std::numeric_limits::min()); + } + + template + Point_cloud(InputIterator first, InputIterator last, Kernel const& k) + : Base(first, last), m_k(k) + { + m_mins.fill(std::numeric_limits::max()); + m_maxs.fill(std::numeric_limits::min()); + } + + void push_back(const Point &point, bool update_bbox = false) + { + Base::push_back(point); + + // Adjust bbox? + if (update_bbox) + { + for (int i = 0 ; i < AMB_DIM ; ++i) + { + if (point.get_param(i) < m_mins[i]) + m_mins[i] = point.get_param(i); + + if (point.get_param(i) > m_maxs[i]) + m_maxs[i] = point.get_param(i); + } + } + } + + void compute_bbox(bool only_if_not_already_done = false) + { + if (only_if_not_already_done && m_mins[0] != std::numeric_limits::max()) + return; + + // Reset + m_mins.fill(std::numeric_limits::max()); + m_maxs.fill(std::numeric_limits::min()); + + // Adjust bbox + for (const auto &point : *this) + { + typedef typename Kernel::Compute_coordinate_d Ccd; + const Ccd ccd = m_k.compute_coordinate_d_object(); + for (int i = 0 ; i < AMB_DIM ; ++i) + { + if (ccd(point, i) < m_mins[i]) + m_mins[i] =ccd(point, i); + + if (ccd(point, i) > m_maxs[i]) + m_maxs[i] = ccd(point, i); + } + } + } + + FT get_min(int dim) const + { + return m_mins[dim]; + } + + FT get_max(int dim) const + { + return m_maxs[dim]; + } + + FT bbox_diagonal() const + { + FT sqdiag = 0; + for (std::size_t i = 0 ; i < AMB_DIM ; ++i) + { + FT d = m_maxs[i] - m_mins[i]; + sqdiag += d*d; + } + return CGAL::sqrt(sqdiag); + } + + void recenter_points_around_origin( + bool compute_bbox_if_not_already_done = true) + { + // If the bounding box has not been computed already + if (m_mins[0] == std::numeric_limits::max()) + if (compute_bbox_if_not_already_done) + compute_bbox(); + else + return; + + // Compute centre of bbox + std::array transl_array; + for (std::size_t i = 0 ; i < AMB_DIM ; ++i) + transl_array[i] = -0.5*(m_maxs[i] + m_mins[i]); + + Point transl(transl_array); + +#ifdef CGAL_LINKED_WITH_TBB + tbb::parallel_for(tbb::blocked_range(0, size()), + [&]( const tbb::blocked_range& r ) + { + for (auto i = r.begin(); i != r.end(); ++i) +#else + for (auto i = 0; i != size(); ++i) +#endif + { + (*this)[i] += transl; + } +#ifdef CGAL_LINKED_WITH_TBB + }); +#endif + + } + +protected: + Kernel const& m_k; //!< A const ref to the kernel + // Bounding box + std::array m_mins; + std::array m_maxs; +}; + + +// And this is the "dataset to kd-tree" adaptor class: +template +class Point_cloud_adaptator +{ +public: + typedef typename Point_cloud_::Kernel Kernel; + typedef typename Point_cloud_::Point Point; + typedef typename Point_cloud_::FT FT; + + /// The constructor that sets the data set source + Point_cloud_adaptator(Point_cloud_ &point_cloud, Kernel const& k) + : m_points(point_cloud), m_k(k) + {} + + /// CRTP helper method + inline Point_cloud_ const& point_cloud() const + { + return m_points; + } + inline Point_cloud_& point_cloud() + { + return m_points; + } + + // Must return the number of data points + inline size_t kdtree_get_point_count() const + { + return point_cloud().size(); + } + + // Returns the distance between the vector "p1[0:size-1]" + // and the data point with index "idx_p2" stored in the class: + inline FT kdtree_distance( + const FT *p1, const size_t idx_p2, size_t size) const + { + Point sp(p1, p1 + size); + return m_k.squared_distance_d_object()(sp, point_cloud()[idx_p2]); + } + + // Returns the dim'th component of the idx'th point in the class: + // Since this is inlined and the "dim" argument is typically an + // immediate value, the "if/else's" are actually solved at compile time. + inline FT kdtree_get_pt(const size_t idx, int dim) const + { + return m_k.compute_coordinate_d_object()(point_cloud()[idx], dim); + } + + // Optional bounding-box computation: return false to default to a standard + // bbox computation loop. + // Return true if the BBOX was already computed by the class and returned + // in "bb" so it can be avoided to redo it again. + // Look at bb.size() to find out the expected dimensionality + // (e.g. 2 or 3 for point clouds) + template + bool kdtree_get_bbox(Bbox &bb) const + { + for (int i = 0 ; i < bb.size() ; ++i) + { + bb[i].low = m_points.get_min(i); + bb[i].high = m_points.get_max(i); + } + + return true; + } + + Kernel const& kernel() const + { + return m_k; + } + +protected: + Point_cloud_& m_points; //!< A ref to the data set origin + Kernel const& m_k; //!< A const ref to the kernel + +}; // end of PointCloudAdaptor + +template +class Point_cloud_data_structure +{ +public: + typedef typename Point_cloud_::Kernel Kernel; + typedef typename Point_cloud_::Point Point; + typedef typename Point_cloud_::FT FT; + + static const int AMB_DIM = Ambient_dimension::value; + + /// Constructor + Point_cloud_data_structure(Point_cloud_ &cloud, Kernel const& k) + : m_adaptor(cloud, k), + m_kd_tree(AMB_DIM, + m_adaptor, + nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) + { + cloud.compute_bbox(true); + //cloud.recenter_points_around_origin(); + m_kd_tree.buildIndex(); + } + + Point_cloud_ &point_cloud() + { + return m_adaptor.point_cloud(); + } + + const Point_cloud_ &point_cloud() const + { + return m_adaptor.point_cloud(); + } + + void query_ANN(const Point &sp, + std::size_t k, + size_t *neighbor_indices, + FT *squared_distance) const + { + /*std::vector sp_vec( + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));*/ // CJTODO remettre + std::vector sp_vec; + for (int i = 0 ; i < 4 ; ++i) + sp_vec.push_back(sp[i]); + nanoflann::KNNResultSet result_set(k); + result_set.init(neighbor_indices, squared_distance); + m_kd_tree.findNeighbors(result_set, + &sp_vec[0], + nanoflann::SearchParams()); + + /*std::cout << "knnSearch(nn="<< num_results <<"): \n"; + for (int i = 0 ; i < num_results ; ++i) + { + std::cout << " * neighbor_indices = " << neighbor_indices [i] + << " (out_dist_sqr = " << squared_distance[i] << ")" + << std::endl; + }*/ + } + + void query_ball(const Point &sp, + const FT radius, + std::vector > &neighbors, + bool sort_output = true) + { + /*std::vector sp_vec( + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));*/ // CJTODO remettre + std::vector sp_vec; + for (int i = 0 ; i < 4 ; ++i) + sp_vec.push_back(sp[i]); + m_kd_tree.radiusSearch(&sp_vec[0], + radius, + neighbors, + nanoflann::SearchParams(32, 0.f, sort_output)); + + /*std::cout << "radiusSearch(num="<< neighbors.size() <<"): \n"; + for (const auto idx_and_dist : neighbors) + { + std::cout << " * neighbor_indices = " << idx_and_dist.first + << " (out_dist_sqr = " << idx_and_dist.second << ")" + << std::endl; + }*/ + } + +protected: + typedef Point_cloud_adaptator Adaptor; + typedef nanoflann::KDTreeSingleIndexAdaptor< + nanoflann::L2_Simple_Adaptor , + Adaptor, + AMB_DIM // dim + > Kd_tree; + + Adaptor m_adaptor; + Kd_tree m_kd_tree; +}; + +} // namespace Tangential_complex_ +} //namespace CGAL + +#endif // POINT_CLOUD_H \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/nanoflann.hpp b/Tangential_complex/include/CGAL/Tangential_complex/nanoflann.hpp new file mode 100644 index 00000000000..8bedc45a2d3 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/nanoflann.hpp @@ -0,0 +1,1449 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * Copyright 2011-2013 Jose Luis Blanco (joseluisblancoc@gmail.com). + * All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef NANOFLANN_HPP_ +#define NANOFLANN_HPP_ + +#include +#include +#include +#include +#include // for fwrite() +#include // for fabs(),... +#include + +// Avoid conflicting declaration of min/max macros in windows headers +#if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64)) +# define NOMINMAX +# ifdef max +# undef max +# undef min +# endif +#endif + +namespace nanoflann +{ +/** @addtogroup nanoflann_grp nanoflann C++ library for ANN + * @{ */ + + /** Library version: 0xMmP (M=Major,m=minor,P=path) */ + #define NANOFLANN_VERSION 0x117 + + /** @addtogroup result_sets_grp Result set classes + * @{ */ + template + class KNNResultSet + { + IndexType * indices; + DistanceType* dists; + CountType capacity; + CountType count; + + public: + inline KNNResultSet(CountType capacity_) : capacity(capacity_), count(0) + { + } + + inline void init(IndexType* indices_, DistanceType* dists_) + { + indices = indices_; + dists = dists_; + count = 0; + dists[capacity-1] = (std::numeric_limits::max)(); + } + + inline CountType size() const + { + return count; + } + + inline bool full() const + { + return count == capacity; + } + + + inline void addPoint(DistanceType dist, IndexType index) + { + CountType i; + for (i=count; i>0; --i) { +#ifdef NANOFLANN_FIRST_MATCH // If defined and two poins have the same distance, the one with the lowest-index will be returned first. + if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) ) { +#else + if (dists[i-1]>dist) { +#endif + if (i + class RadiusResultSet + { + public: + const DistanceType radius; + + std::vector >& m_indices_dists; + + inline RadiusResultSet(DistanceType radius_, std::vector >& indices_dists) : radius(radius_), m_indices_dists(indices_dists) + { + init(); + } + + inline ~RadiusResultSet() { } + + inline void init() { clear(); } + inline void clear() { m_indices_dists.clear(); } + + inline size_t size() const { return m_indices_dists.size(); } + + inline bool full() const { return true; } + + inline void addPoint(DistanceType dist, IndexType index) + { + if (dist 0 + */ + std::pair worst_item() const + { + if (m_indices_dists.empty()) throw std::runtime_error("Cannot invoke RadiusResultSet::worst_item() on an empty list of results."); + typedef typename std::vector >::const_iterator DistIt; + DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end()); + return *it; + } + }; + + /** operator "<" for std::sort() */ + struct IndexDist_Sorter + { + /** PairType will be typically: std::pair */ + template + inline bool operator()(const PairType &p1, const PairType &p2) const { + return p1.second < p2.second; + } + }; + + /** @} */ + + + /** @addtogroup loadsave_grp Load/save auxiliary functions + * @{ */ + template + void save_value(FILE* stream, const T& value, size_t count = 1) + { + fwrite(&value, sizeof(value),count, stream); + } + + template + void save_value(FILE* stream, const std::vector& value) + { + size_t size = value.size(); + fwrite(&size, sizeof(size_t), 1, stream); + fwrite(&value[0], sizeof(T), size, stream); + } + + template + void load_value(FILE* stream, T& value, size_t count = 1) + { + size_t read_cnt = fread(&value, sizeof(value), count, stream); + if (read_cnt != count) { + throw std::runtime_error("Cannot read from file"); + } + } + + + template + void load_value(FILE* stream, std::vector& value) + { + size_t size; + size_t read_cnt = fread(&size, sizeof(size_t), 1, stream); + if (read_cnt!=1) { + throw std::runtime_error("Cannot read from file"); + } + value.resize(size); + read_cnt = fread(&value[0], sizeof(T), size, stream); + if (read_cnt!=size) { + throw std::runtime_error("Cannot read from file"); + } + } + /** @} */ + + + /** @addtogroup metric_grp Metric (distance) classes + * @{ */ + + template inline T abs(T x) { return (x<0) ? -x : x; } + template<> inline int abs(int x) { return ::abs(x); } + template<> inline float abs(float x) { return fabsf(x); } + template<> inline double abs(double x) { return fabs(x); } + template<> inline long double abs(long double x) { return fabsl(x); } + + /** Manhattan distance functor (generic version, optimized for high-dimensionality data sets). + * Corresponding distance traits: nanoflann::metric_L1 + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t) + */ + template + struct L1_Adaptor + { + typedef T ElementType; + typedef _DistanceType DistanceType; + + const DataSource &data_source; + + L1_Adaptor(const DataSource &_data_source) : data_source(_data_source) { } + + inline DistanceType operator()(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const + { + DistanceType result = DistanceType(); + const T* last = a + size; + const T* lastgroup = last - 3; + size_t d = 0; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + const DistanceType diff0 = nanoflann::abs(a[0] - data_source.kdtree_get_pt(b_idx,d++)); + const DistanceType diff1 = nanoflann::abs(a[1] - data_source.kdtree_get_pt(b_idx,d++)); + const DistanceType diff2 = nanoflann::abs(a[2] - data_source.kdtree_get_pt(b_idx,d++)); + const DistanceType diff3 = nanoflann::abs(a[3] - data_source.kdtree_get_pt(b_idx,d++)); + result += diff0 + diff1 + diff2 + diff3; + a += 4; + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 components. Not needed for standard vector lengths. */ + while (a < last) { + result += nanoflann::abs( *a++ - data_source.kdtree_get_pt(b_idx,d++) ); + } + return result; + } + + template + inline DistanceType accum_dist(const U a, const V b, int ) const + { + return nanoflann::abs(a-b); + } + }; + + /** Squared Euclidean distance functor (generic version, optimized for high-dimensionality data sets). + * Corresponding distance traits: nanoflann::metric_L2 + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t) + */ + template + struct L2_Adaptor + { + typedef T ElementType; + typedef _DistanceType DistanceType; + + const DataSource &data_source; + + L2_Adaptor(const DataSource &_data_source) : data_source(_data_source) { } + + inline DistanceType operator()(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const + { + DistanceType result = DistanceType(); + const T* last = a + size; + const T* lastgroup = last - 3; + size_t d = 0; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++); + const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++); + const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++); + const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++); + result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; + a += 4; + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 components. Not needed for standard vector lengths. */ + while (a < last) { + const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++); + result += diff0 * diff0; + } + return result; + } + + template + inline DistanceType accum_dist(const U a, const V b, int ) const + { + return (a-b)*(a-b); + } + }; + + /** Squared Euclidean distance functor (suitable for low-dimensionality datasets, like 2D or 3D point clouds) + * Corresponding distance traits: nanoflann::metric_L2_Simple + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t) + */ + template + struct L2_Simple_Adaptor + { + typedef T ElementType; + typedef _DistanceType DistanceType; + + const DataSource &data_source; + + L2_Simple_Adaptor(const DataSource &_data_source) : data_source(_data_source) { } + + inline DistanceType operator()(const T* a, const size_t b_idx, size_t size) const { + return data_source.kdtree_distance(a,b_idx,size); + } + + template + inline DistanceType accum_dist(const U a, const V b, int ) const + { + return (a-b)*(a-b); + } + }; + + /** Metaprogramming helper traits class for the L1 (Manhattan) metric */ + struct metric_L1 { + template + struct traits { + typedef L1_Adaptor distance_t; + }; + }; + /** Metaprogramming helper traits class for the L2 (Euclidean) metric */ + struct metric_L2 { + template + struct traits { + typedef L2_Adaptor distance_t; + }; + }; + /** Metaprogramming helper traits class for the L2_simple (Euclidean) metric */ + struct metric_L2_Simple { + template + struct traits { + typedef L2_Simple_Adaptor distance_t; + }; + }; + + /** @} */ + + + + /** @addtogroup param_grp Parameter structs + * @{ */ + + /** Parameters (see http://code.google.com/p/nanoflann/ for help choosing the parameters) + */ + struct KDTreeSingleIndexAdaptorParams + { + KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10, int dim_ = -1) : + leaf_max_size(_leaf_max_size), dim(dim_) + {} + + size_t leaf_max_size; + int dim; + }; + + /** Search options for KDTreeSingleIndexAdaptor::findNeighbors() */ + struct SearchParams + { + /** Note: The first argument (checks_IGNORED_) is ignored, but kept for compatibility with the FLANN interface */ + SearchParams(int checks_IGNORED_ = 32, float eps_ = 0, bool sorted_ = true ) : + checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {} + + int checks; //!< Ignored parameter (Kept for compatibility with the FLANN interface). + float eps; //!< search for eps-approximate neighbours (default: 0) + bool sorted; //!< only for radius search, require neighbours sorted by distance (default: true) + }; + /** @} */ + + + /** @addtogroup memalloc_grp Memory allocation + * @{ */ + + /** + * Allocates (using C's malloc) a generic type T. + * + * Params: + * count = number of instances to allocate. + * Returns: pointer (of type T*) to memory buffer + */ + template + inline T* allocate(size_t count = 1) + { + T* mem = (T*) ::malloc(sizeof(T)*count); + return mem; + } + + + /** + * Pooled storage allocator + * + * The following routines allow for the efficient allocation of storage in + * small chunks from a specified pool. Rather than allowing each structure + * to be freed individually, an entire pool of storage is freed at once. + * This method has two advantages over just using malloc() and free(). First, + * it is far more efficient for allocating small objects, as there is + * no overhead for remembering all the information needed to free each + * object or consolidating fragmented memory. Second, the decision about + * how long to keep an object is made at the time of allocation, and there + * is no need to track down all the objects to free them. + * + */ + + const size_t WORDSIZE=16; + const size_t BLOCKSIZE=8192; + + class PooledAllocator + { + /* We maintain memory alignment to word boundaries by requiring that all + allocations be in multiples of the machine wordsize. */ + /* Size of machine word in bytes. Must be power of 2. */ + /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */ + + + size_t remaining; /* Number of bytes left in current block of storage. */ + void* base; /* Pointer to base of current block of storage. */ + void* loc; /* Current location in block to next allocate memory. */ + size_t blocksize; + + void internal_init() + { + remaining = 0; + base = NULL; + usedMemory = 0; + wastedMemory = 0; + } + + public: + size_t usedMemory; + size_t wastedMemory; + + /** + Default constructor. Initializes a new pool. + */ + PooledAllocator(const size_t blocksize_ = BLOCKSIZE) : blocksize(blocksize_) { + internal_init(); + } + + /** + * Destructor. Frees all the memory allocated in this pool. + */ + ~PooledAllocator() { + free_all(); + } + + /** Frees all allocated memory chunks */ + void free_all() + { + while (base != NULL) { + void *prev = *((void**) base); /* Get pointer to prev block. */ + ::free(base); + base = prev; + } + internal_init(); + } + + /** + * Returns a pointer to a piece of new memory of the given size in bytes + * allocated from the pool. + */ + void* malloc(const size_t req_size) + { + /* Round size up to a multiple of wordsize. The following expression + only works for WORDSIZE that is a power of 2, by masking last bits of + incremented size to zero. + */ + const size_t size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1); + + /* Check whether a new block must be allocated. Note that the first word + of a block is reserved for a pointer to the previous block. + */ + if (size > remaining) { + + wastedMemory += remaining; + + /* Allocate new storage. */ + const size_t blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ? + size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE; + + // use the standard C malloc to allocate memory + void* m = ::malloc(blocksize); + if (!m) { + fprintf(stderr,"Failed to allocate memory.\n"); + return NULL; + } + + /* Fill first word of new block with pointer to previous block. */ + ((void**) m)[0] = base; + base = m; + + size_t shift = 0; + //int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1); + + remaining = blocksize - sizeof(void*) - shift; + loc = ((char*)m + sizeof(void*) + shift); + } + void* rloc = loc; + loc = (char*)loc + size; + remaining -= size; + + usedMemory += size; + + return rloc; + } + + /** + * Allocates (using this pool) a generic type T. + * + * Params: + * count = number of instances to allocate. + * Returns: pointer (of type T*) to memory buffer + */ + template + T* allocate(const size_t count = 1) + { + T* mem = (T*) this->malloc(sizeof(T)*count); + return mem; + } + + }; + /** @} */ + + /** @addtogroup nanoflann_metaprog_grp Auxiliary metaprogramming stuff + * @{ */ + + // ---------------- CArray ------------------------- + /** A STL container (as wrapper) for arrays of constant size defined at compile time (class imported from the MRPT project) + * This code is an adapted version from Boost, modifed for its integration + * within MRPT (JLBC, Dec/2009) (Renamed array -> CArray to avoid possible potential conflicts). + * See + * http://www.josuttis.com/cppcode + * for details and the latest version. + * See + * http://www.boost.org/libs/array for Documentation. + * for documentation. + * + * (C) Copyright Nicolai M. Josuttis 2001. + * Permission to copy, use, modify, sell and distribute this software + * is granted provided this copyright notice appears in all copies. + * This software is provided "as is" without express or implied + * warranty, and with no claim as to its suitability for any purpose. + * + * 29 Jan 2004 - minor fixes (Nico Josuttis) + * 04 Dec 2003 - update to synch with library TR1 (Alisdair Meredith) + * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries. + * 05 Aug 2001 - minor update (Nico Josuttis) + * 20 Jan 2001 - STLport fix (Beman Dawes) + * 29 Sep 2000 - Initial Revision (Nico Josuttis) + * + * Jan 30, 2004 + */ + template + class CArray { + public: + T elems[N]; // fixed-size array of elements of type T + + public: + // type definitions + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // iterator support + inline iterator begin() { return elems; } + inline const_iterator begin() const { return elems; } + inline iterator end() { return elems+N; } + inline const_iterator end() const { return elems+N; } + + // reverse iterator support +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) + // workaround for broken reverse_iterator in VC7 + typedef std::reverse_iterator > reverse_iterator; + typedef std::reverse_iterator > const_reverse_iterator; +#else + // workaround for broken reverse_iterator implementations + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#endif + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + // operator[] + inline reference operator[](size_type i) { return elems[i]; } + inline const_reference operator[](size_type i) const { return elems[i]; } + // at() with range check + reference at(size_type i) { rangecheck(i); return elems[i]; } + const_reference at(size_type i) const { rangecheck(i); return elems[i]; } + // front() and back() + reference front() { return elems[0]; } + const_reference front() const { return elems[0]; } + reference back() { return elems[N-1]; } + const_reference back() const { return elems[N-1]; } + // size is constant + static inline size_type size() { return N; } + static bool empty() { return false; } + static size_type max_size() { return N; } + enum { static_size = N }; + /** This method has no effects in this class, but raises an exception if the expected size does not match */ + inline void resize(const size_t nElements) { if (nElements!=N) throw std::logic_error("Try to change the size of a CArray."); } + // swap (note: linear complexity in N, constant for given instantiation) + void swap (CArray& y) { std::swap_ranges(begin(),end(),y.begin()); } + // direct access to data (read-only) + const T* data() const { return elems; } + // use array as C array (direct read/write access to data) + T* data() { return elems; } + // assignment with type conversion + template CArray& operator= (const CArray& rhs) { + std::copy(rhs.begin(),rhs.end(), begin()); + return *this; + } + // assign one value to all elements + inline void assign (const T& value) { for (size_t i=0;i= size()) { throw std::out_of_range("CArray<>: index out of range"); } } + }; // end of CArray + + /** Used to declare fixed-size arrays when DIM>0, dynamically-allocated vectors when DIM=-1. + * Fixed size version for a generic DIM: + */ + template + struct array_or_vector_selector + { + typedef CArray container_t; + }; + /** Dynamic size version */ + template + struct array_or_vector_selector<-1,T> { + typedef std::vector container_t; + }; + /** @} */ + + /** @addtogroup kdtrees_grp KD-tree classes and adaptors + * @{ */ + + /** kd-tree index + * + * Contains the k-d trees and other information for indexing a set of points + * for nearest-neighbor matching. + * + * The class "DatasetAdaptor" must provide the following interface (can be non-virtual, inlined methods): + * + * \code + * // Must return the number of data points + * inline size_t kdtree_get_point_count() const { ... } + * + * // Must return the Euclidean (L2) distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class: + * inline DistanceType kdtree_distance(const T *p1, const size_t idx_p2,size_t size) const { ... } + * + * // Must return the dim'th component of the idx'th point in the class: + * inline T kdtree_get_pt(const size_t idx, int dim) const { ... } + * + * // Optional bounding-box computation: return false to default to a standard bbox computation loop. + * // Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again. + * // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds) + * template + * bool kdtree_get_bbox(BBOX &bb) const + * { + * bb[0].low = ...; bb[0].high = ...; // 0th dimension limits + * bb[1].low = ...; bb[1].high = ...; // 1st dimension limits + * ... + * return true; + * } + * + * \endcode + * + * \tparam IndexType Will be typically size_t or int + */ + template + class KDTreeSingleIndexAdaptor + { + public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::DistanceType DistanceType; + protected: + + /** + * Array of indices to vectors in the dataset. + */ + std::vector vind; + + size_t m_leaf_max_size; + + + /** + * The dataset used by this index + */ + const DatasetAdaptor &dataset; //!< The source of our data + + const KDTreeSingleIndexAdaptorParams index_params; + + size_t m_size; + int dim; //!< Dimensionality of each data point + + + /*--------------------- Internal Data Structures --------------------------*/ + struct Node + { + union { + struct + { + /** + * Indices of points in leaf node + */ + IndexType left, right; + } lr; + struct + { + /** + * Dimension used for subdivision. + */ + int divfeat; + /** + * The values used for subdivision. + */ + DistanceType divlow, divhigh; + } sub; + }; + /** + * The child nodes. + */ + Node* child1, * child2; + }; + typedef Node* NodePtr; + + + struct Interval + { + ElementType low, high; + }; + + /** Define "BoundingBox" as a fixed-size or variable-size container depending on "DIM" */ + typedef typename array_or_vector_selector::container_t BoundingBox; + + /** Define "distance_vector_t" as a fixed-size or variable-size container depending on "DIM" */ + typedef typename array_or_vector_selector::container_t distance_vector_t; + + /** This record represents a branch point when finding neighbors in + the tree. It contains a record of the minimum distance to the query + point, as well as the node at which the search resumes. + */ + template + struct BranchStruct + { + T node; /* Tree node at which search resumes */ + DistanceType mindist; /* Minimum distance to query for all nodes below. */ + + BranchStruct() {} + BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {} + + inline bool operator<(const BranchStruct& rhs) const + { + return mindist BranchSt; + typedef BranchSt* Branch; + + BoundingBox root_bbox; + + /** + * Pooled memory allocator. + * + * Using a pooled memory allocator is more efficient + * than allocating memory directly when there is a large + * number small of memory allocations. + */ + PooledAllocator pool; + + public: + + Distance distance; + + /** + * KDTree constructor + * + * Params: + * inputData = dataset with the input features + * params = parameters passed to the kdtree algorithm (see http://code.google.com/p/nanoflann/ for help choosing the parameters) + */ + KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor& inputData, const KDTreeSingleIndexAdaptorParams& params = KDTreeSingleIndexAdaptorParams() ) : + dataset(inputData), index_params(params), root_node(NULL), distance(inputData) + { + m_size = dataset.kdtree_get_point_count(); + dim = dimensionality; + if (DIM>0) dim=DIM; + else { + if (params.dim>0) dim = params.dim; + } + m_leaf_max_size = params.leaf_max_size; + + // Create a permutable array of indices to the input vectors. + init_vind(); + } + + /** + * Standard destructor + */ + ~KDTreeSingleIndexAdaptor() + { + } + + /** Frees the previously-built index. Automatically called within buildIndex(). */ + void freeIndex() + { + pool.free_all(); + root_node=NULL; + } + + /** + * Builds the index + */ + void buildIndex() + { + init_vind(); + computeBoundingBox(root_bbox); + freeIndex(); + root_node = divideTree(0, m_size, root_bbox ); // construct the tree + } + + /** + * Returns size of index. + */ + size_t size() const + { + return m_size; + } + + /** + * Returns the length of an index feature. + */ + size_t veclen() const + { + return static_cast(DIM>0 ? DIM : dim); + } + + /** + * Computes the inde memory usage + * Returns: memory used by the index + */ + size_t usedMemory() const + { + return pool.usedMemory+pool.wastedMemory+dataset.kdtree_get_point_count()*sizeof(IndexType); // pool memory and vind array memory + } + + /** \name Query methods + * @{ */ + + /** + * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored inside + * the result object. + * + * Params: + * result = the result object in which the indices of the nearest-neighbors are stored + * vec = the vector for which to search the nearest neighbors + * + * \tparam RESULTSET Should be any ResultSet + * \sa knnSearch, radiusSearch + */ + template + void findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParams& searchParams) const + { + assert(vec); + if (!root_node) throw std::runtime_error("[nanoflann] findNeighbors() called before building the index."); + float epsError = 1+searchParams.eps; + + distance_vector_t dists; // fixed or variable-sized container (depending on DIM) + dists.assign((DIM>0 ? DIM : dim) ,0); // Fill it with zeros. + DistanceType distsq = computeInitialDistances(vec, dists); + searchLevel(result, vec, root_node, distsq, dists, epsError); // "count_leaf" parameter removed since was neither used nor returned to the user. + } + + /** + * Find the "num_closest" nearest neighbors to the \a query_point[0:dim-1]. Their indices are stored inside + * the result object. + * \sa radiusSearch, findNeighbors + * \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface. + */ + inline void knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int nChecks_IGNORED = 10) const + { + nanoflann::KNNResultSet resultSet(num_closest); + resultSet.init(out_indices, out_distances_sq); + this->findNeighbors(resultSet, query_point, nanoflann::SearchParams()); + } + + /** + * Find all the neighbors to \a query_point[0:dim-1] within a maximum radius. + * The output is given as a vector of pairs, of which the first element is a point index and the second the corresponding distance. + * Previous contents of \a IndicesDists are cleared. + * + * If searchParams.sorted==true, the output list is sorted by ascending distances. + * + * For a better performance, it is advisable to do a .reserve() on the vector if you have any wild guess about the number of expected matches. + * + * \sa knnSearch, findNeighbors + * \return The number of points within the given radius (i.e. indices.size() or dists.size() ) + */ + size_t radiusSearch(const ElementType *query_point,const DistanceType radius, std::vector >& IndicesDists, const SearchParams& searchParams) const + { + RadiusResultSet resultSet(radius,IndicesDists); + this->findNeighbors(resultSet, query_point, searchParams); + + if (searchParams.sorted) + std::sort(IndicesDists.begin(),IndicesDists.end(), IndexDist_Sorter() ); + + return resultSet.size(); + } + + /** @} */ + + private: + /** Make sure the auxiliary list \a vind has the same size than the current dataset, and re-generate if size has changed. */ + void init_vind() + { + // Create a permutable array of indices to the input vectors. + m_size = dataset.kdtree_get_point_count(); + if (vind.size()!=m_size) vind.resize(m_size); + for (size_t i = 0; i < m_size; i++) vind[i] = i; + } + + /// Helper accessor to the dataset points: + inline ElementType dataset_get(size_t idx, int component) const { + return dataset.kdtree_get_pt(idx,component); + } + + + void save_tree(FILE* stream, NodePtr tree) + { + save_value(stream, *tree); + if (tree->child1!=NULL) { + save_tree(stream, tree->child1); + } + if (tree->child2!=NULL) { + save_tree(stream, tree->child2); + } + } + + + void load_tree(FILE* stream, NodePtr& tree) + { + tree = pool.allocate(); + load_value(stream, *tree); + if (tree->child1!=NULL) { + load_tree(stream, tree->child1); + } + if (tree->child2!=NULL) { + load_tree(stream, tree->child2); + } + } + + + void computeBoundingBox(BoundingBox& bbox) + { + bbox.resize((DIM>0 ? DIM : dim)); + if (dataset.kdtree_get_bbox(bbox)) + { + // Done! It was implemented in derived class + } + else + { + for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { + bbox[i].low = + bbox[i].high = dataset_get(0,i); + } + const size_t N = dataset.kdtree_get_point_count(); + for (size_t k=1; k0 ? DIM : dim); ++i) { + if (dataset_get(k,i)bbox[i].high) bbox[i].high = dataset_get(k,i); + } + } + } + } + + + /** + * Create a tree node that subdivides the list of vecs from vind[first] + * to vind[last]. The routine is called recursively on each sublist. + * Place a pointer to this new tree node in the location pTree. + * + * Params: pTree = the new node to create + * first = index of the first vector + * last = index of the last vector + */ + NodePtr divideTree(const IndexType left, const IndexType right, BoundingBox& bbox) + { + NodePtr node = pool.allocate(); // allocate memory + + /* If too few exemplars remain, then make this a leaf node. */ + if ( (right-left) <= m_leaf_max_size) { + node->child1 = node->child2 = NULL; /* Mark as leaf node. */ + node->lr.left = left; + node->lr.right = right; + + // compute bounding-box of leaf points + for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { + bbox[i].low = dataset_get(vind[left],i); + bbox[i].high = dataset_get(vind[left],i); + } + for (IndexType k=left+1; k0 ? DIM : dim); ++i) { + if (bbox[i].low>dataset_get(vind[k],i)) bbox[i].low=dataset_get(vind[k],i); + if (bbox[i].highsub.divfeat = cutfeat; + + BoundingBox left_bbox(bbox); + left_bbox[cutfeat].high = cutval; + node->child1 = divideTree(left, left+idx, left_bbox); + + BoundingBox right_bbox(bbox); + right_bbox[cutfeat].low = cutval; + node->child2 = divideTree(left+idx, right, right_bbox); + + node->sub.divlow = left_bbox[cutfeat].high; + node->sub.divhigh = right_bbox[cutfeat].low; + + for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { + bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low); + bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high); + } + } + + return node; + } + + void computeMinMax(IndexType* ind, IndexType count, int element, ElementType& min_elem, ElementType& max_elem) + { + min_elem = dataset_get(ind[0],element); + max_elem = dataset_get(ind[0],element); + for (IndexType i=1; imax_elem) max_elem = val; + } + } + + void middleSplit(IndexType* ind, IndexType count, IndexType& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox) + { + // find the largest span from the approximate bounding box + ElementType max_span = bbox[0].high-bbox[0].low; + cutfeat = 0; + cutval = (bbox[0].high+bbox[0].low)/2; + for (int i=1; i<(DIM>0 ? DIM : dim); ++i) { + ElementType span = bbox[i].low-bbox[i].low; + if (span>max_span) { + max_span = span; + cutfeat = i; + cutval = (bbox[i].high+bbox[i].low)/2; + } + } + + // compute exact span on the found dimension + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + cutval = (min_elem+max_elem)/2; + max_span = max_elem - min_elem; + + // check if a dimension of a largest span exists + size_t k = cutfeat; + for (size_t i=0; i<(DIM>0 ? DIM : dim); ++i) { + if (i==k) continue; + ElementType span = bbox[i].high-bbox[i].low; + if (span>max_span) { + computeMinMax(ind, count, i, min_elem, max_elem); + span = max_elem - min_elem; + if (span>max_span) { + max_span = span; + cutfeat = i; + cutval = (min_elem+max_elem)/2; + } + } + } + IndexType lim1, lim2; + planeSplit(ind, count, cutfeat, cutval, lim1, lim2); + + if (lim1>count/2) index = lim1; + else if (lim2(0.00001); + ElementType max_span = bbox[0].high-bbox[0].low; + for (int i=1; i<(DIM>0 ? DIM : dim); ++i) { + ElementType span = bbox[i].high-bbox[i].low; + if (span>max_span) { + max_span = span; + } + } + ElementType max_spread = -1; + cutfeat = 0; + for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { + ElementType span = bbox[i].high-bbox[i].low; + if (span>(1-EPS)*max_span) { + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + ElementType spread = max_elem-min_elem;; + if (spread>max_spread) { + cutfeat = i; + max_spread = spread; + } + } + } + // split in the middle + DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2; + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + + if (split_valmax_elem) cutval = max_elem; + else cutval = split_val; + + IndexType lim1, lim2; + planeSplit(ind, count, cutfeat, cutval, lim1, lim2); + + if (lim1>count/2) index = lim1; + else if (lim2cutval + */ + void planeSplit(IndexType* ind, const IndexType count, int cutfeat, DistanceType cutval, IndexType& lim1, IndexType& lim2) + { + /* Move vector indices for left subtree to front of list. */ + IndexType left = 0; + IndexType right = count-1; + for (;; ) { + while (left<=right && dataset_get(ind[left],cutfeat)=cutval) --right; + if (left>right || !right) break; // "!right" was added to support unsigned Index types + std::swap(ind[left], ind[right]); + ++left; + --right; + } + /* If either list is empty, it means that all remaining features + * are identical. Split in the middle to maintain a balanced tree. + */ + lim1 = left; + right = count-1; + for (;; ) { + while (left<=right && dataset_get(ind[left],cutfeat)<=cutval) ++left; + while (right && left<=right && dataset_get(ind[right],cutfeat)>cutval) --right; + if (left>right || !right) break; // "!right" was added to support unsigned Index types + std::swap(ind[left], ind[right]); + ++left; + --right; + } + lim2 = left; + } + + DistanceType computeInitialDistances(const ElementType* vec, distance_vector_t& dists) const + { + assert(vec); + DistanceType distsq = 0.0; + + for (int i = 0; i < (DIM>0 ? DIM : dim); ++i) { + if (vec[i] < root_bbox[i].low) { + dists[i] = distance.accum_dist(vec[i], root_bbox[i].low, i); + distsq += dists[i]; + } + if (vec[i] > root_bbox[i].high) { + dists[i] = distance.accum_dist(vec[i], root_bbox[i].high, i); + distsq += dists[i]; + } + } + + return distsq; + } + + /** + * Performs an exact search in the tree starting from a node. + * \tparam RESULTSET Should be any ResultSet + */ + template + void searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq, + distance_vector_t& dists, const float epsError) const + { + /* If this is a leaf node, then do check and return. */ + if ((node->child1 == NULL)&&(node->child2 == NULL)) { + //count_leaf += (node->lr.right-node->lr.left); // Removed since was neither used nor returned to the user. + DistanceType worst_dist = result_set.worstDist(); + for (IndexType i=node->lr.left; ilr.right; ++i) { + const IndexType index = vind[i];// reorder... : i; + DistanceType dist = distance(vec, index, (DIM>0 ? DIM : dim)); + if (distsub.divfeat; + ElementType val = vec[idx]; + DistanceType diff1 = val - node->sub.divlow; + DistanceType diff2 = val - node->sub.divhigh; + + NodePtr bestChild; + NodePtr otherChild; + DistanceType cut_dist; + if ((diff1+diff2)<0) { + bestChild = node->child1; + otherChild = node->child2; + cut_dist = distance.accum_dist(val, node->sub.divhigh, idx); + } + else { + bestChild = node->child2; + otherChild = node->child1; + cut_dist = distance.accum_dist( val, node->sub.divlow, idx); + } + + /* Call recursively to search next level down. */ + searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError); + + DistanceType dst = dists[idx]; + mindistsq = mindistsq + cut_dist - dst; + dists[idx] = cut_dist; + if (mindistsq*epsError<=result_set.worstDist()) { + searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError); + } + dists[idx] = dst; + } + + public: + /** Stores the index in a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so when loading the index object it must be constructed associated to the same source of data points used while building it. + * See the example: examples/saveload_example.cpp + * \sa loadIndex */ + void saveIndex(FILE* stream) + { + save_value(stream, m_size); + save_value(stream, dim); + save_value(stream, root_bbox); + save_value(stream, m_leaf_max_size); + save_value(stream, vind); + save_tree(stream, root_node); + } + + /** Loads a previous index from a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so the index object must be constructed associated to the same source of data points used while building the index. + * See the example: examples/saveload_example.cpp + * \sa loadIndex */ + void loadIndex(FILE* stream) + { + load_value(stream, m_size); + load_value(stream, dim); + load_value(stream, root_bbox); + load_value(stream, m_leaf_max_size); + load_value(stream, vind); + load_tree(stream, root_node); + } + + }; // class KDTree + + + /** A simple KD-tree adaptor for working with data directly stored in an Eigen Matrix, without duplicating the data storage. + * Each row in the matrix represents a point in the state space. + * + * Example of usage: + * \code + * Eigen::Matrix mat; + * // Fill out "mat"... + * + * typedef KDTreeEigenMatrixAdaptor< Eigen::Matrix > my_kd_tree_t; + * const int max_leaf = 10; + * my_kd_tree_t mat_index(dimdim, mat, max_leaf ); + * mat_index.index->buildIndex(); + * mat_index.index->... + * \endcode + * + * \tparam DIM If set to >0, it specifies a compile-time fixed dimensionality for the points in the data set, allowing more compiler optimizations. + * \tparam Distance The distance metric to use: nanoflann::metric_L1, nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. + * \tparam IndexType The type for indices in the KD-tree index (typically, size_t of int) + */ + template + struct KDTreeEigenMatrixAdaptor + { + typedef KDTreeEigenMatrixAdaptor self_t; + typedef typename MatrixType::Scalar num_t; + typedef typename Distance::template traits::distance_t metric_t; + typedef KDTreeSingleIndexAdaptor< metric_t,self_t,DIM,IndexType> index_t; + + index_t* index; //! The kd-tree index for the user to call its methods as usual with any other FLANN index. + + /// Constructor: takes a const ref to the matrix object with the data points + KDTreeEigenMatrixAdaptor(const int dimensionality, const MatrixType &mat, const int leaf_max_size = 10) : m_data_matrix(mat) + { + const size_t dims = mat.cols(); + if (DIM>0 && static_cast(dims)!=DIM) + throw std::runtime_error("Data set dimensionality does not match the 'DIM' template argument"); + index = new index_t( dims, *this /* adaptor */, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size, dims ) ); + index->buildIndex(); + } + + ~KDTreeEigenMatrixAdaptor() { + delete index; + } + + const MatrixType &m_data_matrix; + + /** Query for the \a num_closest closest points to a given point (entered as query_point[0:dim-1]). + * Note that this is a short-cut method for index->findNeighbors(). + * The user can also call index->... methods as desired. + * \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface. + */ + inline void query(const num_t *query_point, const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq, const int nChecks_IGNORED = 10) const + { + nanoflann::KNNResultSet resultSet(num_closest); + resultSet.init(out_indices, out_distances_sq); + index->findNeighbors(resultSet, query_point, nanoflann::SearchParams()); + } + + /** @name Interface expected by KDTreeSingleIndexAdaptor + * @{ */ + + const self_t & derived() const { + return *this; + } + self_t & derived() { + return *this; + } + + // Must return the number of data points + inline size_t kdtree_get_point_count() const { + return m_data_matrix.rows(); + } + + // Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class: + inline num_t kdtree_distance(const num_t *p1, const size_t idx_p2,size_t size) const + { + num_t s=0; + for (size_t i=0; i + bool kdtree_get_bbox(BBOX &bb) const { + return false; + } + + /** @} */ + + }; // end of KDTreeEigenMatrixAdaptor + /** @} */ + +/** @} */ // end of grouping +} // end of NS + + +#endif /* NANOFLANN_HPP_ */ diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 2ce238cc8c1..f58ace643b3 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -23,11 +23,11 @@ #include #include +#include #include namespace CGAL { - namespace Tangential_complex_ { template @@ -70,7 +70,7 @@ namespace Tangential_complex_ { return output_basis; } -}; // namespace Tangential_complex_ +} // namespace Tangential_complex_ } //namespace CGAL #endif // CGAL_TC_UTILITIES_H From 92873230e16305997356c5acd29e377e9bdcdd94 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 11:08:47 +0200 Subject: [PATCH 091/487] Remove the using and call the base's operator() explicitly --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 1526c084885..cec297a9550 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -89,16 +89,15 @@ public: struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{ PointPropertyMap ppmap; - using Base_traits::Construct_cartesian_const_iterator_d::operator(); Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_) :Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){} typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p) const - { return this->operator() (get(ppmap,p)); } + { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p)); } typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const - { return this->operator() (get(ppmap,p),0); } + { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p),0); } }; struct Construct_iso_box_d: public Base::Construct_iso_box_d{ From e41c06324b09fd96e850c2b922b451bcfe0573cd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 11:15:22 +0200 Subject: [PATCH 092/487] Use CGAL's spatial searching + change the computation of the "star sphere" (Waiting for a patch in Cartesian_wrap so that it works correctly) --- .../include/CGAL/Tangential_complex.h | 101 ++++-- .../CGAL/Tangential_complex/Point_cloud.h | 292 +++++++----------- .../include/CGAL/Tangential_complex/config.h | 7 +- 3 files changed, 196 insertions(+), 204 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f2ee98ccef8..2cdb28ee3c4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -91,9 +91,9 @@ class Tangential_complex typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; - typedef typename std::vector Tangent_space_basis; - - typedef Point_cloud Points; + typedef std::vector Tangent_space_basis; + + typedef std::vector Points; typedef Point_cloud_data_structure Points_ds; typedef std::pair Tr_and_VH; @@ -119,7 +119,7 @@ public: template Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), m_points(first, last, k), m_points_ds(m_points, k) {} + : m_k(k), m_points(first, last), m_points_ds(m_points, k) {} /// Destructor ~Tangential_complex() {} @@ -335,13 +335,17 @@ private: const Tr_traits &local_tr_traits = p_local_tr->geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; - // Traits functor & objects - Tr_traits::Center_of_sphere_d center_of_sphere = - local_tr_traits.center_of_sphere_d_object(); + // Kernel functor & objects + //Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); // CJTODO: use that + Get_functor::type k_diff_pts(m_k); + + // Triangulation's traits functor & objects Tr_traits::Squared_distance_d sqdist = local_tr_traits.squared_distance_d_object(); Tr_traits::Point_drop_weight_d drop_w = local_tr_traits.point_drop_weight_d_object(); + Tr_traits::Center_of_sphere_d center_of_sphere = + local_tr_traits.center_of_sphere_d_object(); // Estimate the tangent space const Point ¢er_pt = m_points[i]; @@ -352,18 +356,27 @@ private: // (we only need the star of p) //*************************************************** + const int NUM_NEIGHBORS = 150; + std::size_t nearest_nb[NUM_NEIGHBORS]; + FT squared_distance[NUM_NEIGHBORS]; + m_points_ds.query_ANN( + center_pt, NUM_NEIGHBORS, nearest_nb, squared_distance); + /*const int NUM_NEIGHBORS = 150; + std::size_t nearest_nb[NUM_NEIGHBORS]; + for (int ii = 0 ; ii < NUM_NEIGHBORS ; ++ii) + nearest_nb[ii] = ii;*/ + // First, compute the projected points std::vector projected_points; FT max_squared_weight = 0; - projected_points.reserve(m_points.size() - 1); - Points::const_iterator it_p = m_points.begin(); - Points::const_iterator it_p_end = m_points.end(); - for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) + projected_points.reserve(NUM_NEIGHBORS); + for (std::size_t j = 0 ; j < NUM_NEIGHBORS ; ++j) { // ith point = p, which is already inserted - if (j != i) + std::size_t idx = nearest_nb[j]; + //if (idx != i) // CJTODO optim? { - Tr_point wp = project_point(*it_p, center_pt, m_tangent_spaces[i]); + Tr_point wp = project_point(m_points[idx], center_pt, m_tangent_spaces[i]); projected_points.push_back(wp); FT w = local_tr_traits.point_weight_d_object()(wp); if (w > max_squared_weight) @@ -384,41 +397,39 @@ private: // While building the local triangulation, we keep the radius // of the sphere centered at "center_vertex" and which contains all the // circumspheres of the star of "center_vertex" - // [TODO?] For now, we use non-weighted circumspheres but it could be - // optimized by using weighted circumspheres (which are smaller) FT star_sphere_squared_radius = std::numeric_limits::max(); // Insert the other points - std::vector::const_iterator it_wp = projected_points.begin(); - it_p = m_points.begin(); - for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) + for (std::size_t j = 0 ; j < NUM_NEIGHBORS ; ++j) { + std::size_t point_idx = nearest_nb[j]; + Tr_point const& proj_pt = projected_points[j]; + // ith point = p, which is already inserted - if (j != i) + if (point_idx != i) { - if (local_tr_traits.squared_distance_d_object()( - drop_w(wp), drop_w(*it_wp)) + if (m_k.squared_distance_d_object()( + center_pt, m_points[point_idx]) > star_sphere_squared_radius) { - ++it_wp; continue; } FT squared_dist_to_tangent_plane = - local_tr_traits.point_weight_d_object()(*it_wp); + local_tr_traits.point_weight_d_object()(proj_pt); FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - drop_w(*it_wp), + drop_w(proj_pt), w); Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); //Tr_vertex_handle vh = p_local_tr->insert(wp); if (vh != Tr_vertex_handle()) { - vh->data() = j; + vh->data() = point_idx; // Let's recompute star_sphere_squared_radius if (p_local_tr->current_dimension() >= Intrinsic_dimension) - { + { star_sphere_squared_radius = 0.; // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; @@ -434,11 +445,40 @@ private: } else { - Tr_vertex_to_bare_point v2p(local_tr_traits); + //********************************* + Tangent_space_basis tsb; + tsb.reserve(Intrinsic_dimension); + Point const& orig = m_points[cell->vertex(0)->data()]; + for (int ii = 1 ; ii <= Intrinsic_dimension ; ++ii) + { + tsb.push_back(k_diff_pts( + m_points[cell->vertex(ii)->data()], orig)); + } + tsb = compute_gram_schmidt_basis(tsb, m_k); + + // CJTODO: write a project_point which returns a Tr_bare_point + // and use it here + std::vector proj_pts; + std::vector::const_iterator it_p = proj_pts.begin(); + std::vector::const_iterator it_p_end = proj_pts.end(); + // For each point p + for (int ii = 0 ; ii <= Intrinsic_dimension ; ++ii) + { + proj_pts.push_back(project_point( + m_points[cell->vertex(ii)->data()], orig, tsb)); + } + Tr_bare_point c = center_of_sphere( - boost::make_transform_iterator(cell->vertices_begin(), v2p), - boost::make_transform_iterator(cell->vertices_end(), v2p)); - FT sq_circumdiam = 4.*sqdist(c, drop_w(center_vertex->point())); + boost::make_transform_iterator(proj_pts.begin(), drop_w), + boost::make_transform_iterator(proj_pts.end(), drop_w)); + + //********************************* + //Tr_vertex_to_global_point v2gp(m_points); + //Point c = k_center_of_sphere( + // boost::make_transform_iterator(cell->vertices_begin(), v2gp), + // boost::make_transform_iterator(cell->vertices_end(), v2gp)); + //********************************* + FT sq_circumdiam = 4.*sqdist(c, drop_w(proj_pts[0])); if (sq_circumdiam > star_sphere_squared_radius) star_sphere_squared_radius = sq_circumdiam; } @@ -446,7 +486,6 @@ private: } } //std::cerr << star_sphere_squared_radius << std::endl; - ++it_wp; } } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 1a130113f7e..6cd815f7e65 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -26,6 +26,8 @@ #include #include +#ifdef CGAL_TC_USE_NANOFLANN + #include "nanoflann.hpp" #include @@ -35,163 +37,26 @@ namespace CGAL { namespace Tangential_complex_ { -template -class Point_cloud -: public std::vector -{ -public: - typedef std::vector Base; - typedef Base Raw_container; - typedef Point_ Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - - //typedef typename Base::iterator iterator; - //typedef typename Base::const_iterator const_iterator; - - static const int AMB_DIM = Ambient_dimension::value; - - Point_cloud(Kernel const& k) - : m_k(k) - { - m_mins.fill(std::numeric_limits::max()); - m_maxs.fill(std::numeric_limits::min()); - } - - template - Point_cloud(InputIterator first, InputIterator last, Kernel const& k) - : Base(first, last), m_k(k) - { - m_mins.fill(std::numeric_limits::max()); - m_maxs.fill(std::numeric_limits::min()); - } - - void push_back(const Point &point, bool update_bbox = false) - { - Base::push_back(point); - - // Adjust bbox? - if (update_bbox) - { - for (int i = 0 ; i < AMB_DIM ; ++i) - { - if (point.get_param(i) < m_mins[i]) - m_mins[i] = point.get_param(i); - - if (point.get_param(i) > m_maxs[i]) - m_maxs[i] = point.get_param(i); - } - } - } - - void compute_bbox(bool only_if_not_already_done = false) - { - if (only_if_not_already_done && m_mins[0] != std::numeric_limits::max()) - return; - - // Reset - m_mins.fill(std::numeric_limits::max()); - m_maxs.fill(std::numeric_limits::min()); - - // Adjust bbox - for (const auto &point : *this) - { - typedef typename Kernel::Compute_coordinate_d Ccd; - const Ccd ccd = m_k.compute_coordinate_d_object(); - for (int i = 0 ; i < AMB_DIM ; ++i) - { - if (ccd(point, i) < m_mins[i]) - m_mins[i] =ccd(point, i); - - if (ccd(point, i) > m_maxs[i]) - m_maxs[i] = ccd(point, i); - } - } - } - - FT get_min(int dim) const - { - return m_mins[dim]; - } - - FT get_max(int dim) const - { - return m_maxs[dim]; - } - - FT bbox_diagonal() const - { - FT sqdiag = 0; - for (std::size_t i = 0 ; i < AMB_DIM ; ++i) - { - FT d = m_maxs[i] - m_mins[i]; - sqdiag += d*d; - } - return CGAL::sqrt(sqdiag); - } - - void recenter_points_around_origin( - bool compute_bbox_if_not_already_done = true) - { - // If the bounding box has not been computed already - if (m_mins[0] == std::numeric_limits::max()) - if (compute_bbox_if_not_already_done) - compute_bbox(); - else - return; - - // Compute centre of bbox - std::array transl_array; - for (std::size_t i = 0 ; i < AMB_DIM ; ++i) - transl_array[i] = -0.5*(m_maxs[i] + m_mins[i]); - - Point transl(transl_array); - -#ifdef CGAL_LINKED_WITH_TBB - tbb::parallel_for(tbb::blocked_range(0, size()), - [&]( const tbb::blocked_range& r ) - { - for (auto i = r.begin(); i != r.end(); ++i) -#else - for (auto i = 0; i != size(); ++i) -#endif - { - (*this)[i] += transl; - } -#ifdef CGAL_LINKED_WITH_TBB - }); -#endif - - } - -protected: - Kernel const& m_k; //!< A const ref to the kernel - // Bounding box - std::array m_mins; - std::array m_maxs; -}; - - -// And this is the "dataset to kd-tree" adaptor class: -template +// "dataset to kd-tree" adaptor class +template class Point_cloud_adaptator { public: - typedef typename Point_cloud_::Kernel Kernel; - typedef typename Point_cloud_::Point Point; - typedef typename Point_cloud_::FT FT; + typedef typename Point_container_::value_type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; /// The constructor that sets the data set source - Point_cloud_adaptator(Point_cloud_ &point_cloud, Kernel const& k) - : m_points(point_cloud), m_k(k) + Point_cloud_adaptator(Point_container_ &points, Kernel const& k) + : m_points(points), m_k(k) {} /// CRTP helper method - inline Point_cloud_ const& point_cloud() const + inline Point_container_ const& points() const { return m_points; } - inline Point_cloud_& point_cloud() + inline Point_container_& points() { return m_points; } @@ -199,7 +64,7 @@ public: // Must return the number of data points inline size_t kdtree_get_point_count() const { - return point_cloud().size(); + return m_points.size(); } // Returns the distance between the vector "p1[0:size-1]" @@ -208,7 +73,7 @@ public: const FT *p1, const size_t idx_p2, size_t size) const { Point sp(p1, p1 + size); - return m_k.squared_distance_d_object()(sp, point_cloud()[idx_p2]); + return m_k.squared_distance_d_object()(sp, points()[idx_p2]); } // Returns the dim'th component of the idx'th point in the class: @@ -216,7 +81,7 @@ public: // immediate value, the "if/else's" are actually solved at compile time. inline FT kdtree_get_pt(const size_t idx, int dim) const { - return m_k.compute_coordinate_d_object()(point_cloud()[idx], dim); + return m_k.compute_coordinate_d_object()(points()[idx], dim); } // Optional bounding-box computation: return false to default to a standard @@ -228,13 +93,7 @@ public: template bool kdtree_get_bbox(Bbox &bb) const { - for (int i = 0 ; i < bb.size() ; ++i) - { - bb[i].low = m_points.get_min(i); - bb[i].high = m_points.get_max(i); - } - - return true; + return false; } Kernel const& kernel() const @@ -243,42 +102,40 @@ public: } protected: - Point_cloud_& m_points; //!< A ref to the data set origin + Point_container_& m_points; //!< A ref to the data set origin Kernel const& m_k; //!< A const ref to the kernel -}; // end of PointCloudAdaptor +}; -template +template class Point_cloud_data_structure { public: - typedef typename Point_cloud_::Kernel Kernel; - typedef typename Point_cloud_::Point Point; - typedef typename Point_cloud_::FT FT; + typedef typename Point_container_::value_type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; static const int AMB_DIM = Ambient_dimension::value; /// Constructor - Point_cloud_data_structure(Point_cloud_ &cloud, Kernel const& k) - : m_adaptor(cloud, k), + Point_cloud_data_structure(Point_container_ &points, Kernel const& k) + : m_adaptor(points, k), m_kd_tree(AMB_DIM, m_adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) { - cloud.compute_bbox(true); - //cloud.recenter_points_around_origin(); m_kd_tree.buildIndex(); } - Point_cloud_ &point_cloud() + /*Point_container_ &points() { - return m_adaptor.point_cloud(); + return m_adaptor.points(); } - const Point_cloud_ &point_cloud() const + const Point_container_ &points() const { - return m_adaptor.point_cloud(); - } + return m_adaptor.points(); + }*/ void query_ANN(const Point &sp, std::size_t k, @@ -332,7 +189,7 @@ public: } protected: - typedef Point_cloud_adaptator Adaptor; + typedef Point_cloud_adaptator Adaptor; typedef nanoflann::KDTreeSingleIndexAdaptor< nanoflann::L2_Simple_Adaptor , Adaptor, @@ -346,4 +203,95 @@ protected: } // namespace Tangential_complex_ } //namespace CGAL +#else // !CGAL_TC_USE_NANOFLANN => use CGAL Spatial searching + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace CGAL { +namespace Tangential_complex_ { + +template +class Point_cloud_data_structure +{ +public: + typedef typename Point_container_::value_type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + typedef boost::tuple Point_and_idx; + typedef CGAL::Search_traits< + FT, Point, + typename Kernel::Cartesian_const_iterator_d, + typename Kernel::Construct_cartesian_const_iterator_d> Traits_base; + typedef CGAL::Search_traits_adapter, + Traits_base> STraits; + + typedef CGAL::Orthogonal_k_neighbor_search K_neighbor_search; + typedef typename K_neighbor_search::Tree Tree; + typedef typename K_neighbor_search::Distance Distance; + + static const int AMB_DIM = Ambient_dimension::value; + + /// Constructor + Point_cloud_data_structure(Point_container_ &points, Kernel const& k) + : m_points(points), + m_tree( + boost::make_zip_iterator(boost::make_tuple( + points.begin(), + boost::counting_iterator(0))), + boost::make_zip_iterator(boost::make_tuple( + points.end(), + boost::counting_iterator(points.size()))) ) + { + } + + /*Point_container_ &points() + { + return m_points; + } + + const Point_container_ &points() const + { + return m_points; + }*/ + + void query_ANN(const Point &sp, + unsigned int k, + size_t *neighbor_indices, + FT *squared_distance) const + { + // Initialize the search structure, and search all N points + K_neighbor_search search(m_tree, sp, k); + // report the N nearest neighbors and their distance + // This should sort all N points by increasing distance from origin + int i = 0; + for(K_neighbor_search::iterator it = search.begin(); + it != search.end(); ++it, ++i) + { + neighbor_indices[i] = boost::get<1>(it->first); + squared_distance[i] = it->second; + } + } + +protected: + Point_container_ const& m_points; + Tree m_tree; +}; + +} // namespace Tangential_complex_ +} //namespace CGAL + +#endif // CGAL_TC_USE_NANOFLANN + #endif // POINT_CLOUD_H \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index a05abf81622..004c5d7c309 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -23,8 +23,13 @@ #include +//========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING -const std::size_t NUM_POINTS_FOR_PCA = 30; +//========================= Strategy ========================================== +//#define CGAL_TC_USE_NANOFLANN + +//========================= Parameters ======================================== +const std::size_t NUM_POINTS_FOR_PCA = 50; #endif // CGAL_TC_CONFIG_H From 7ae85ffac3797048482ea208127f868019461819 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 11:16:05 +0200 Subject: [PATCH 093/487] More points! --- .../test/Tangential_complex/test_tangential_complex.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index a44ed2fe252..82626f91dde 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -1,3 +1,5 @@ +//#undef CGAL_LINKED_WITH_TBB // CJTODO TEMP + // Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB // (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/) #ifdef _DEBUG @@ -18,9 +20,9 @@ #endif #ifdef _DEBUG - const int NUM_POINTS = 50; + const int NUM_POINTS = 150; #else - const int NUM_POINTS = 5000; + const int NUM_POINTS = 50000; #endif template From 144856e4aec1cb87f0df8761a7035e239c67fa3f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 15:47:59 +0200 Subject: [PATCH 094/487] Add explicit forwarder to the Base_traits --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index cec297a9550..ce0e10e24fb 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -89,7 +89,7 @@ public: struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{ PointPropertyMap ppmap; - + Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_) :Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){} @@ -98,6 +98,12 @@ public: typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p),0); } + + typename Base_traits::Cartesian_const_iterator_d operator()(const typename Base_traits::Point_d& p) const + { return Base_traits::Construct_cartesian_const_iterator_d::operator() (p); } + + typename Base_traits::Cartesian_const_iterator_d operator()(const typename Base_traits::Point_d& p, int) const + { return Base_traits::Construct_cartesian_const_iterator_d::operator() (p,0); } }; struct Construct_iso_box_d: public Base::Construct_iso_box_d{ From 6037445c5074609eca601fa0c13b8fd023ea02ab Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 16:30:46 +0200 Subject: [PATCH 095/487] Add a comment about the two new operators --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index ce0e10e24fb..c5d629a0358 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -99,6 +99,11 @@ public: typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p),0); } + // These 2 additional operators forward the call to Base_traits. + // This is needed because of an undocumented requirement of + // Orthogonal_k_neighbor_search and Orthogonal_incremental_neighbor_search: + // Traits::Construct_cartesian_const_iterator should be callable + // on the query point type typename Base_traits::Cartesian_const_iterator_d operator()(const typename Base_traits::Point_d& p) const { return Base_traits::Construct_cartesian_const_iterator_d::operator() (p); } From bf946d4e87ac461caabd915789e771a3276288f7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 16:51:12 +0200 Subject: [PATCH 096/487] Temporarily remove spatial_sort as it was wrong --- .../include/CGAL/Regular_triangulation.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index d0552b6d7eb..db42946fe1e 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -23,6 +23,8 @@ #include #include #include +#include +#include namespace CGAL { @@ -219,14 +221,13 @@ public: size_type n = number_of_vertices(); typedef std::vector WP_vec; WP_vec points(start, end); - typename Geom_traits::Point_drop_weight_d pdw = - geom_traits().point_drop_weight_d_object(); - spatial_sort( - boost::make_transform_iterator(points.begin(), pdw), - boost::make_transform_iterator(points.end(), pdw), - typename Geom_traits::Base()); - //spatial_sort(points.begin(), points.end(), geom_traits()); // CJTODO TEMP A REMETTRE - //spatial_sort(points.begin(), points.end(), Geom_traits::Base()); + + // CJTODO remettre et corriger + /*typedef CGAL::Spatial_sort_traits_adapter_d< + Geom_traits, typename Geom_traits::Point_drop_weight_d> Search_traits_d; + Search_traits_d st_d(geom_traits().point_drop_weight_d_object()); + spatial_sort(points.begin(), points.end(), st_d);*/ + Full_cell_handle hint; for(typename WP_vec::const_iterator p = points.begin(); p != points.end(); ++p ) { From d6255a16f09a141abff001366b4f8495482010cd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 16:56:47 +0200 Subject: [PATCH 097/487] Fix syntax --- Triangulation/include/CGAL/Delaunay_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 3cb65fff2d1..b144fa99c3b 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -150,7 +150,7 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS - Delaunay_triangulation(int dim, &const Geom_traits k = Geom_traits()) + Delaunay_triangulation(int dim, const Geom_traits &k = Geom_traits()) : Base(dim, k) { } From 43c8a1d0ba10cd5ad1d9828cbb6f294577bf9b6a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 17:00:00 +0200 Subject: [PATCH 098/487] Just stores indices in the search tree --- .../include/CGAL/Tangential_complex.h | 6 +- .../CGAL/Tangential_complex/Point_cloud.h | 67 +++++++++++++------ 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2cdb28ee3c4..00ade4c9b65 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -358,9 +358,8 @@ private: const int NUM_NEIGHBORS = 150; std::size_t nearest_nb[NUM_NEIGHBORS]; - FT squared_distance[NUM_NEIGHBORS]; m_points_ds.query_ANN( - center_pt, NUM_NEIGHBORS, nearest_nb, squared_distance); + center_pt, NUM_NEIGHBORS, nearest_nb); /*const int NUM_NEIGHBORS = 150; std::size_t nearest_nb[NUM_NEIGHBORS]; for (int ii = 0 ; ii < NUM_NEIGHBORS ; ++ii) @@ -509,9 +508,8 @@ private: Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); std::size_t neighbor_indices[NUM_POINTS_FOR_PCA]; - FT squared_distance[NUM_POINTS_FOR_PCA]; m_points_ds.query_ANN( - p, NUM_POINTS_FOR_PCA, neighbor_indices, squared_distance); + p, NUM_POINTS_FOR_PCA, neighbor_indices); //******************************* PCA ************************************* diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 6cd815f7e65..7452028d9c3 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -225,17 +225,16 @@ class Point_cloud_data_structure { public: typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; - typedef boost::tuple Point_and_idx; typedef CGAL::Search_traits< - FT, Point, + FT, Point, typename Kernel::Cartesian_const_iterator_d, typename Kernel::Construct_cartesian_const_iterator_d> Traits_base; - typedef CGAL::Search_traits_adapter, - Traits_base> STraits; + // using a pointer as a special property map type + typedef CGAL::Search_traits_adapter< + std::ptrdiff_t, Point*, Traits_base> STraits; typedef CGAL::Orthogonal_k_neighbor_search K_neighbor_search; typedef typename K_neighbor_search::Tree Tree; @@ -244,15 +243,13 @@ public: static const int AMB_DIM = Ambient_dimension::value; /// Constructor - Point_cloud_data_structure(Point_container_ &points, Kernel const& k) + Point_cloud_data_structure(Point_container_ const& points, Kernel const& k) : m_points(points), m_tree( - boost::make_zip_iterator(boost::make_tuple( - points.begin(), - boost::counting_iterator(0))), - boost::make_zip_iterator(boost::make_tuple( - points.end(), - boost::counting_iterator(points.size()))) ) + boost::counting_iterator(0), + boost::counting_iterator(points.size()), + Tree::Splitter(), + STraits((Point*)&(points[0])) ) { } @@ -265,22 +262,48 @@ public: { return m_points; }*/ - + + template void query_ANN(const Point &sp, unsigned int k, - size_t *neighbor_indices, - FT *squared_distance) const + IndexOutputIt indices_out) const { // Initialize the search structure, and search all N points - K_neighbor_search search(m_tree, sp, k); + // Note that we need to pass the Distance explicitly since it needs to + // know the property map + K_neighbor_search search(m_tree, sp, k, FT(0.1), true, + Distance_adapter >( + (Point*)&(m_points[0])) ); + // report the N nearest neighbors and their distance // This should sort all N points by increasing distance from origin - int i = 0; for(K_neighbor_search::iterator it = search.begin(); - it != search.end(); ++it, ++i) + it != search.end(); ++it) { - neighbor_indices[i] = boost::get<1>(it->first); - squared_distance[i] = it->second; + *indices_out++ = it->first; + } + } + + template + void query_ANN(const Point &sp, + unsigned int k, + IndexOutputIt indices_out, + DistanceOutputIt distances_out) const + { + // Initialize the search structure, and search all N points + // Note that we need to pass the Distance explicitly since it needs to + // know the property map + K_neighbor_search search(m_tree, sp, k, FT(0.1), true, + Distance_adapter >( + (Point*)&(m_points[0])) ); + + // report the N nearest neighbors and their distance + // This should sort all N points by increasing distance from origin + for(K_neighbor_search::iterator it = search.begin(); + it != search.end(); ++it) + { + *indices_out++ = it->first; + *distances_out++ = it->second; } } From 121fabd2648c1df95b8e480fd1f41cccd6d5577e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 17:04:26 +0200 Subject: [PATCH 099/487] Removed some "auto" keywords --- .../include/CGAL/Regular_triangulation_euclidean_traits.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 6a4e993ae9a..3f5a9630a85 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -189,9 +189,7 @@ public: const Weighted_point_d & p, const int i) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - auto pp = pdw(p); - auto ddsd = m_kernel.compute_coordinate_d_object(); - ddsd(pp, i); + m_kernel.compute_coordinate_d_object()(pdw(p), i); return m_kernel.compute_coordinate_d_object()(pdw(p), i); } }; From a7b58d60d419c3e072f14405ef9938902e82a191 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 12 Sep 2014 18:34:44 +0200 Subject: [PATCH 100/487] Try a different way to avoid returning a reference to a temporary. The previous workaround was giving us iterators into temporaries :-( --- .../CGAL/NewKernel_d/Cartesian_LA_functors.h | 2 +- .../CGAL/NewKernel_d/Types/Weighted_point.h | 4 ++-- .../CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h | 9 ++++---- .../include/CGAL/transforming_iterator.h | 22 ++++++++++++++----- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h index 7aa1a265300..871c463ac77 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h @@ -180,7 +180,7 @@ template struct Compute_cartesian_coordinate { #ifdef CGAL_CXX11 typedef decltype(std::declval()[0]) result_type; #else - typedef RT result_type; + typedef RT const& result_type; // RT const& doesn't work with some LA (Eigen2 for instance) so we // should use plain RT or find a way to detect this. #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 47593a3990e..32e8b586b58 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -57,8 +57,8 @@ template struct Construct_weighted_point : Store_kernel { template struct Point_drop_weight { CGAL_FUNCTOR_INIT_IGNORE(Point_drop_weight) typedef typename Get_type::type argument_type; - typedef typename Get_type::type result_type; - // Returning a reference would be too fragile + typedef typename Get_type::type const& result_type; + // Returning a reference is fragile result_type operator()(argument_type const&s)const{ return s.point(); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h index 43ed894e4e5..520a96c8e9e 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h @@ -79,17 +79,16 @@ struct Forward_rep { //}; //#else template ::value,bool=Is_wrapper_iterator::value> struct result_; -template struct result_{typedef T type;}; // const& -template struct result_{typedef typename decay::type::Rep type;}; // const& +template struct result_{typedef T const& type;}; +template struct result_{typedef typename decay::type::Rep const& type;}; template struct result_{typedef transforming_iterator::type> type;}; template struct result; template struct result : result_ {}; -template typename boost::disable_if,Is_wrapper_iterator >,T>::type operator()(T const& t) const {return t;} // const& +template typename boost::disable_if,Is_wrapper_iterator >,T>::type const& operator()(T const& t) const {return t;} template typename boost::disable_if,Is_wrapper_iterator >,T>::type& operator()(T& t) const {return t;} -// FIXME: We should return const&, but it causes trouble inside a transform_iterator of an iterator that returns a prvalue :-( -template typename T::Rep operator()(T const& t, typename boost::enable_if >::type* = 0) const {return t.rep();} +template typename T::Rep const& operator()(T const& t, typename boost::enable_if >::type* = 0) const {return t.rep();} template transforming_iterator,T>::type> operator()(T const& t) const {return make_transforming_iterator(t,Forward_rep());} //#endif diff --git a/NewKernel_d/include/CGAL/transforming_iterator.h b/NewKernel_d/include/CGAL/transforming_iterator.h index 186901bc086..15ea19a59ee 100644 --- a/NewKernel_d/include/CGAL/transforming_iterator.h +++ b/NewKernel_d/include/CGAL/transforming_iterator.h @@ -22,6 +22,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -54,23 +58,31 @@ template struct Functor_as_base : public T { template class transforming_iterator_helper { + typedef std::iterator_traits Iter_traits; + typedef typename Iter_traits::reference Iter_ref; typedef typename Default::Get()(std::declval::reference>())) + decltype(std::declval()(std::declval())) #else - typename boost::result_of::value_type)>::type + typename boost::result_of::type // should be reference instead of value_type #endif - >::type reference; + >::type reference_; - typedef typename Default::Get::type>::type>::type value_type; + typedef typename Default::Get::type>::type>::type value_type; + + // Crappy heuristic. If we have *it that returns a Weighted_point and F that returns a reference to the Point contained in the Weighted_point it takes as argument, we do NOT want the transformed iterator to return a reference to the temporary *it. On the other hand, if *it returns an int n, and F returns a reference to array[n] it is not so good to lose the reference. This probably should be done elsewhere and should at least be made optional... + typedef typename boost::mpl::if_< + boost::mpl::or_, + boost::is_integral >, + reference_, value_type>::type reference; public: typedef boost::iterator_adaptor< Derived, Iter, value_type, - typename std::iterator_traits::iterator_category, + typename Iter_traits::iterator_category, reference > type; }; From a2f9041d546d194afada4b318ca3212da40ecb9e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sun, 14 Sep 2014 09:06:21 +0200 Subject: [PATCH 101/487] Fix spatial_sort --- .../include/CGAL/Regular_triangulation.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index db42946fe1e..b5174b0f698 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -26,6 +26,8 @@ #include #include +#include + namespace CGAL { template< typename RTTraits, typename TDS_ = Default > @@ -221,12 +223,16 @@ public: size_type n = number_of_vertices(); typedef std::vector WP_vec; WP_vec points(start, end); - - // CJTODO remettre et corriger - /*typedef CGAL::Spatial_sort_traits_adapter_d< - Geom_traits, typename Geom_traits::Point_drop_weight_d> Search_traits_d; - Search_traits_d st_d(geom_traits().point_drop_weight_d_object()); - spatial_sort(points.begin(), points.end(), st_d);*/ + + typedef boost::function_property_map< + typename Geom_traits::Point_drop_weight_d, + Point, + Bare_point> Drop_weight_pmap; + typedef CGAL::Spatial_sort_traits_adapter_d< + typename Geom_traits::Base, Drop_weight_pmap> Search_traits_d; + Search_traits_d st_d(boost::make_function_property_map( + geom_traits().point_drop_weight_d_object())); + spatial_sort(points.begin(), points.end(), st_d); Full_cell_handle hint; for(typename WP_vec::const_iterator p = points.begin(); p != points.end(); ++p ) From 2bc5d62429ae24ef082bd932bd47a5e525366824 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 15 Sep 2014 14:32:38 +0200 Subject: [PATCH 102/487] Comment some tests --- Triangulation/test/Triangulation/test_regular.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index cbfb021a058..d1a6c568777 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -122,11 +122,10 @@ int main(int argc, char **argv) int N = 10; if( argc > 1 ) N = atoi(argv[1]); - go<5>(N); - go<4>(N); + //go<5>(N); + //go<4>(N); go<3>(N); go<2>(N); - go<1>(N); cerr << endl; return 0; From 7682e0265fc6586ab485675d0faa521087adcc92 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Sep 2014 10:40:35 +0200 Subject: [PATCH 103/487] Change Point_cloud interface + add incremental ANN --- .../include/CGAL/Tangential_complex.h | 39 +++++++---- .../CGAL/Tangential_complex/Point_cloud.h | 67 ++++++++++--------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 00ade4c9b65..8d8f93f0a80 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -95,6 +95,10 @@ class Tangential_complex typedef std::vector Points; typedef Point_cloud_data_structure Points_ds; + typedef typename Points_ds::KNS_range KNS_range; + typedef typename Points_ds::KNS_iterator KNS_iterator; + typedef typename Points_ds::INS_range INS_range; + typedef typename Points_ds::INS_iterator INS_iterator; typedef std::pair Tr_and_VH; typedef typename std::vector Tr_container; @@ -336,8 +340,8 @@ private: Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; // Kernel functor & objects - //Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); // CJTODO: use that - Get_functor::type k_diff_pts(m_k); + Kernel::Difference_of_points_d k_diff_pts = + m_k.difference_of_points_d_object(); // Triangulation's traits functor & objects Tr_traits::Squared_distance_d sqdist = @@ -357,9 +361,8 @@ private: //*************************************************** const int NUM_NEIGHBORS = 150; - std::size_t nearest_nb[NUM_NEIGHBORS]; - m_points_ds.query_ANN( - center_pt, NUM_NEIGHBORS, nearest_nb); + KNS_range const& ins_range = + m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); /*const int NUM_NEIGHBORS = 150; std::size_t nearest_nb[NUM_NEIGHBORS]; for (int ii = 0 ; ii < NUM_NEIGHBORS ; ++ii) @@ -367,12 +370,18 @@ private: // First, compute the projected points std::vector projected_points; + std::vector nearest_nb; + nearest_nb.reserve(NUM_NEIGHBORS); FT max_squared_weight = 0; projected_points.reserve(NUM_NEIGHBORS); - for (std::size_t j = 0 ; j < NUM_NEIGHBORS ; ++j) + KNS_iterator nn_it = ins_range.begin(); + for (std::size_t j = 0 ; + j < NUM_NEIGHBORS && nn_it != ins_range.end() ; + ++j, ++nn_it) { // ith point = p, which is already inserted - std::size_t idx = nearest_nb[j]; + std::size_t idx = nn_it->first; + nearest_nb.push_back(idx); //if (idx != i) // CJTODO optim? { Tr_point wp = project_point(m_points[idx], center_pt, m_tangent_spaces[i]); @@ -507,19 +516,21 @@ private: Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - std::size_t neighbor_indices[NUM_POINTS_FOR_PCA]; - m_points_ds.query_ANN( - p, NUM_POINTS_FOR_PCA, neighbor_indices); + KNS_range kns_range = m_points_ds.query_ANN( + p, NUM_POINTS_FOR_PCA, false); //******************************* PCA ************************************* const int amb_dim = Ambient_dimension::value; // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); - for (int j = 0 ; j < NUM_POINTS_FOR_PCA ; ++j) + KNS_iterator nn_it = kns_range.begin(); + for (int j = 0 ; + j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + ++j, ++nn_it) { for (int i = 0 ; i < amb_dim ; ++i) - mat_points(j, i) = m_points[neighbor_indices[j]][i]; // CJTODO: Use kernel functor + mat_points(j, i) = m_points[nn_it->first][i]; // CJTODO: Use kernel functor } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -580,8 +591,8 @@ private: const Tangent_space_basis &ts) const { Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - //Kernel::Difference_of_points_d diff_points= m_k.difference_of_points_d_object(); // CJTODO: use that - Get_functor::type diff_points(m_k); + Kernel::Difference_of_points_d diff_points = + m_k.difference_of_points_d_object(); std::vector coords; // Ambiant-space coords of the projected point diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 7452028d9c3..8cc5e68fe19 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -206,6 +206,7 @@ protected: #else // !CGAL_TC_USE_NANOFLANN => use CGAL Spatial searching #include +#include #include #include #include @@ -213,6 +214,7 @@ protected: #include #include #include +#include #include #include @@ -239,6 +241,14 @@ public: typedef CGAL::Orthogonal_k_neighbor_search K_neighbor_search; typedef typename K_neighbor_search::Tree Tree; typedef typename K_neighbor_search::Distance Distance; + typedef typename K_neighbor_search::iterator KNS_iterator; + typedef K_neighbor_search KNS_range; + + typedef CGAL::Orthogonal_incremental_neighbor_search< + STraits, Distance, CGAL::Sliding_midpoint, Tree> + Incremental_neighbor_search; + typedef typename Incremental_neighbor_search::iterator INS_iterator; + typedef Incremental_neighbor_search INS_range; static const int AMB_DIM = Ambient_dimension::value; @@ -262,49 +272,42 @@ public: { return m_points; }*/ - - template - void query_ANN(const Point &sp, + + KNS_range query_ANN(const + Point &sp, unsigned int k, - IndexOutputIt indices_out) const + bool sorted = true) const { // Initialize the search structure, and search all N points // Note that we need to pass the Distance explicitly since it needs to // know the property map - K_neighbor_search search(m_tree, sp, k, FT(0.1), true, - Distance_adapter >( - (Point*)&(m_points[0])) ); - - // report the N nearest neighbors and their distance - // This should sort all N points by increasing distance from origin - for(K_neighbor_search::iterator it = search.begin(); - it != search.end(); ++it) - { - *indices_out++ = it->first; - } + K_neighbor_search search( + m_tree, + sp, + k, + FT(0.0), + true, + Distance_adapter >( + (Point*)&(m_points[0])), + sorted); + + return search; } - - template - void query_ANN(const Point &sp, - unsigned int k, - IndexOutputIt indices_out, - DistanceOutputIt distances_out) const + + INS_range query_incremental_ANN(const Point &sp) const { // Initialize the search structure, and search all N points // Note that we need to pass the Distance explicitly since it needs to // know the property map - K_neighbor_search search(m_tree, sp, k, FT(0.1), true, - Distance_adapter >( + Incremental_neighbor_search search( + m_tree, + sp, + FT(0.0), + true, + Distance_adapter >( (Point*)&(m_points[0])) ); - - // report the N nearest neighbors and their distance - // This should sort all N points by increasing distance from origin - for(K_neighbor_search::iterator it = search.begin(); - it != search.end(); ++it) - { - *indices_out++ = it->first; - *distances_out++ = it->second; - } + + return search; } protected: From 4c2dbee682260251e99776545adeb1f3d29e362c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Sep 2014 10:43:35 +0200 Subject: [PATCH 104/487] Clean-up --- Tangential_complex/include/CGAL/Tangential_complex.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8d8f93f0a80..8fe02476d54 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -361,12 +361,8 @@ private: //*************************************************** const int NUM_NEIGHBORS = 150; - KNS_range const& ins_range = + KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); - /*const int NUM_NEIGHBORS = 150; - std::size_t nearest_nb[NUM_NEIGHBORS]; - for (int ii = 0 ; ii < NUM_NEIGHBORS ; ++ii) - nearest_nb[ii] = ii;*/ // First, compute the projected points std::vector projected_points; From 6b1658000b89da2d739b443a1a2f8182f30cd6d3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Sep 2014 15:56:55 +0200 Subject: [PATCH 105/487] Do not compute max_squared_weight, just use a big value instead + bugfix This needs to be improved (what big value should we use?). Bugfix: the weight stored inside the points are squared weights, but the computations were done like it was non-squared weights. --- .../include/CGAL/Tangential_complex.h | 138 +++++++++--------- 1 file changed, 68 insertions(+), 70 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8fe02476d54..aabd14c23da 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -100,20 +100,38 @@ class Tangential_complex typedef typename Points_ds::INS_range INS_range; typedef typename Points_ds::INS_iterator INS_iterator; - typedef std::pair Tr_and_VH; + // Store a local triangulation and a handle to its center vertex + struct Tr_and_VH + { + public: + Tr_and_VH() + : m_tr(NULL) {} + Tr_and_VH(int dim) + : m_tr(new Triangulation(dim)) {} + + ~Tr_and_VH() { delete m_tr; } + + Triangulation & construct_triangulation(int dim) + { + m_tr = new Triangulation(dim); + return tr(); + } + + Triangulation & tr() { return *m_tr; } + Triangulation const& tr() const { return *m_tr; } + + + Tr_vertex_handle const& center_vertex() const { return m_center_vertex; } + Tr_vertex_handle & center_vertex() { return m_center_vertex; } + + private: + Triangulation* m_tr; + Tr_vertex_handle m_center_vertex; + }; + typedef typename std::vector Tr_container; typedef typename std::vector TS_container; - // Stores the index of the original Point in the ambient space - /*struct Tr_point_with_index - : public Tr_point - { - Tr_point_with_index(const Tr_point &p, std::size_t i) - : Tr_point(p), index(i) {} - - std::size_t index; - };*/ - public: /// Constructor Tangential_complex(const Kernel &k = Kernel()) @@ -137,9 +155,7 @@ public: // We need to do that because we don't want the container to copy the // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations - m_triangulations.resize( - m_points.size(), - std::make_pair((Triangulation*)NULL, Tr_vertex_handle())); + m_triangulations.resize(m_points.size()); m_tangent_spaces.resize(m_points.size()); #ifdef CGAL_LINKED_WITH_TBB @@ -221,15 +237,15 @@ public: // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { - const Triangulation &tr = *it_tr->first; - Tr_vertex_handle center_vh = it_tr->second; + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); std::vector::const_iterator it_c = incident_cells.begin(); std::vector::const_iterator it_c_end= incident_cells.end(); - // For each triangulation + // For each cell for ( ; it_c != it_c_end ; ++it_c) { output << Intrinsic_dimension + 1 << " "; @@ -333,11 +349,10 @@ private: void compute_tangent_triangulation(std::size_t i) { //std::cerr << "***********************************************" << std::endl; - Triangulation *p_local_tr = - m_triangulations[i].first = - new Triangulation(Intrinsic_dimension); - const Tr_traits &local_tr_traits = p_local_tr->geom_traits(); - Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; + Triangulation &local_tr = + m_triangulations[i].construct_triangulation(Intrinsic_dimension); + const Tr_traits &local_tr_traits = local_tr.geom_traits(); + Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects Kernel::Difference_of_points_d k_diff_pts = @@ -359,58 +374,40 @@ private: // Build a minimal triangulation in the tangent space // (we only need the star of p) //*************************************************** + + // CJTODO: replace 1000000 with something better + + // Insert p + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(0, 0), + 1000000); + center_vertex = local_tr.insert(wp); + center_vertex->data() = i; const int NUM_NEIGHBORS = 150; - KNS_range ins_range = - m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); + //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); + INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); + + // While building the local triangulation, we keep the radius + // of the sphere centered at "center_vertex" and which contains all the + // circumspheres of the star of "center_vertex" + FT star_sphere_squared_radius = std::numeric_limits::max(); - // First, compute the projected points - std::vector projected_points; - std::vector nearest_nb; - nearest_nb.reserve(NUM_NEIGHBORS); - FT max_squared_weight = 0; - projected_points.reserve(NUM_NEIGHBORS); - KNS_iterator nn_it = ins_range.begin(); + INS_iterator nn_it = ins_range.begin(); for (std::size_t j = 0 ; j < NUM_NEIGHBORS && nn_it != ins_range.end() ; ++j, ++nn_it) { // ith point = p, which is already inserted - std::size_t idx = nn_it->first; - nearest_nb.push_back(idx); - //if (idx != i) // CJTODO optim? - { - Tr_point wp = project_point(m_points[idx], center_pt, m_tangent_spaces[i]); - projected_points.push_back(wp); - FT w = local_tr_traits.point_weight_d_object()(wp); - if (w > max_squared_weight) - max_squared_weight = w; - } - } - - // Now we can insert the points - - // Insert p - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(0, 0), - CGAL::sqrt(max_squared_weight)); - center_vertex = p_local_tr->insert(wp); - center_vertex->data() = i; - //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; - - // While building the local triangulation, we keep the radius - // of the sphere centered at "center_vertex" and which contains all the - // circumspheres of the star of "center_vertex" - FT star_sphere_squared_radius = std::numeric_limits::max(); - // Insert the other points - for (std::size_t j = 0 ; j < NUM_NEIGHBORS ; ++j) - { - std::size_t point_idx = nearest_nb[j]; - Tr_point const& proj_pt = projected_points[j]; + std::size_t point_idx = nn_it->first; // ith point = p, which is already inserted if (point_idx != i) { + Tr_point proj_pt = project_point( + m_points[point_idx], center_pt, m_tangent_spaces[i]); + + // CJTODO: voir if (m_k.squared_distance_d_object()( center_pt, m_points[point_idx]) > star_sphere_squared_radius) @@ -420,29 +417,29 @@ private: FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); - FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); + FT w = 1000000 - squared_dist_to_tangent_plane; Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( drop_w(proj_pt), w); - Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); - //Tr_vertex_handle vh = p_local_tr->insert(wp); + Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); + //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) { vh->data() = point_idx; // Let's recompute star_sphere_squared_radius - if (p_local_tr->current_dimension() >= Intrinsic_dimension) + if (local_tr.current_dimension() >= Intrinsic_dimension) { star_sphere_squared_radius = 0.; // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; - p_local_tr->incident_full_cells( + local_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); for (auto cell : incident_cells) // CJTODO C++11 { - if (p_local_tr->is_infinite(cell)) + if (local_tr.is_infinite(cell)) { star_sphere_squared_radius = std::numeric_limits::max(); break; @@ -493,14 +490,15 @@ private: } } + // CJTODO DEBUG //std::cerr << "\nChecking topology and geometry..." - // << (p_local_tr->is_valid(true) ? "OK.\n" : "Error.\n"); + // << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); // DEBUG: output the local mesh into an OFF file //std::stringstream sstr; //sstr << "data/local_tri_" << i << ".off"; //std::ofstream off_stream_tr(sstr.str()); - //CGAL::export_triangulation_to_off(off_stream_tr, *p_local_tr); + //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } Tangent_space_basis compute_tangent_space(const Point &p) const From e23ac137ce6d265541d745b9be65b983974b6828 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 16:04:24 +0200 Subject: [PATCH 106/487] No fixed NUM_NEIGHBORS anymore + improved code for projection Insert points until we find a point which is outside the sphere centered the "center vertex" and which contains all the circumspheres of the star of this "center vertex" --- .../include/CGAL/Tangential_complex.h | 90 +++++++++++-------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index aabd14c23da..aad9f85681d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -357,6 +357,8 @@ private: // Kernel functor & objects Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); + Kernel::Squared_distance_d k_sqdist = + m_k.squared_distance_d_object(); // Triangulation's traits functor & objects Tr_traits::Squared_distance_d sqdist = @@ -384,36 +386,33 @@ private: center_vertex = local_tr.insert(wp); center_vertex->data() = i; - const int NUM_NEIGHBORS = 150; + //const int NUM_NEIGHBORS = 150; //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); // While building the local triangulation, we keep the radius - // of the sphere centered at "center_vertex" and which contains all the + // of the sphere "star sphere" centered at "center_vertex" + // and which contains all the // circumspheres of the star of "center_vertex" FT star_sphere_squared_radius = std::numeric_limits::max(); - INS_iterator nn_it = ins_range.begin(); - for (std::size_t j = 0 ; - j < NUM_NEIGHBORS && nn_it != ins_range.end() ; - ++j, ++nn_it) + // Insert points until we find a point which is outside "star shere" + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) { - // ith point = p, which is already inserted - std::size_t point_idx = nn_it->first; + std::size_t neighbor_point_idx = nn_it->first; // ith point = p, which is already inserted - if (point_idx != i) + if (neighbor_point_idx != i) { - Tr_point proj_pt = project_point( - m_points[point_idx], center_pt, m_tangent_spaces[i]); + const Point &neighbor_pt = m_points[neighbor_point_idx]; - // CJTODO: voir - if (m_k.squared_distance_d_object()( - center_pt, m_points[point_idx]) - > star_sphere_squared_radius) - { - continue; - } + if (k_sqdist(center_pt, neighbor_pt) > star_sphere_squared_radius) + break; + + Tr_point proj_pt = project_point_and_compute_weight( + neighbor_pt, center_pt, m_tangent_spaces[i]); FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); @@ -426,7 +425,7 @@ private: //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) { - vh->data() = point_idx; + vh->data() = neighbor_point_idx; // Let's recompute star_sphere_squared_radius if (local_tr.current_dimension() >= Intrinsic_dimension) @@ -447,6 +446,14 @@ private: else { //********************************* + // We don't compute the circumsphere of the simplex in the + // local tangent plane since it would involve to take the + // weights of the points into account later + // (which is a problem since the ANN is performed on the + // points in the ambient dimension) + // Instead, we compute the subspace defined by the simplex + // and we compute the circumsphere in this subspace + // and we extract the diameter Tangent_space_basis tsb; tsb.reserve(Intrinsic_dimension); Point const& orig = m_points[cell->vertex(0)->data()]; @@ -457,11 +464,8 @@ private: } tsb = compute_gram_schmidt_basis(tsb, m_k); - // CJTODO: write a project_point which returns a Tr_bare_point - // and use it here - std::vector proj_pts; - std::vector::const_iterator it_p = proj_pts.begin(); - std::vector::const_iterator it_p_end = proj_pts.end(); + std::vector proj_pts; + proj_pts.reserve(Intrinsic_dimension + 1); // For each point p for (int ii = 0 ; ii <= Intrinsic_dimension ; ++ii) { @@ -470,16 +474,9 @@ private: } Tr_bare_point c = center_of_sphere( - boost::make_transform_iterator(proj_pts.begin(), drop_w), - boost::make_transform_iterator(proj_pts.end(), drop_w)); + proj_pts.begin(), proj_pts.end()); - //********************************* - //Tr_vertex_to_global_point v2gp(m_points); - //Point c = k_center_of_sphere( - // boost::make_transform_iterator(cell->vertices_begin(), v2gp), - // boost::make_transform_iterator(cell->vertices_end(), v2gp)); - //********************************* - FT sq_circumdiam = 4.*sqdist(c, drop_w(proj_pts[0])); + FT sq_circumdiam = 4.*sqdist(c, proj_pts[0]); if (sq_circumdiam > star_sphere_squared_radius) star_sphere_squared_radius = sq_circumdiam; } @@ -578,11 +575,34 @@ private: //return compute_gram_schmidt_basis(ts, m_k); */ } + + // Project the point in the tangent space + // The weight will be the squared distance between p and the projection of p + Tr_bare_point project_point(const Point &p, const Point &origin, + const Tangent_space_basis &ts) const + { + Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); + Kernel::Difference_of_points_d diff_points = + m_k.difference_of_points_d_object(); + + std::vector coords; + // Ambiant-space coords of the projected point + coords.reserve(Intrinsic_dimension); + for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) + { + // Compute the inner product p * ts[i] + Vector v = diff_points(p, origin); + FT coord = inner_pdct(v, ts[i]); + coords.push_back(coord); + } + + return Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()); + } // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p - Tr_point project_point(const Point &p, const Point &origin, - const Tangent_space_basis &ts) const + Tr_point project_point_and_compute_weight( + const Point &p, const Point &origin, const Tangent_space_basis &ts) const { Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); Kernel::Difference_of_points_d diff_points = From fcbc96fbf843cf060824f6df56d798f60447462b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 16:14:17 +0200 Subject: [PATCH 107/487] Rename WallClockTimer => Wall_clock_timer (internal timer using TBB timers if available) --- Mesh_3/demo/Mesh_3/Mesh_function.h | 2 +- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h | 6 +++--- Mesh_3/include/CGAL/Mesh_3/Mesher_3.h | 4 ++-- Mesh_3/include/CGAL/Mesh_3/Mesher_level.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h | 8 ++++---- Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h | 4 ++-- Tangential_complex/include/CGAL/Tangential_complex.h | 2 +- Triangulation_3/include/CGAL/Delaunay_triangulation_3.h | 4 ++-- Triangulation_3/include/CGAL/Regular_triangulation_3.h | 4 ++-- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Mesh_3/demo/Mesh_3/Mesh_function.h b/Mesh_3/demo/Mesh_3/Mesh_function.h index b9e8e8e7147..d6d6a5a7f01 100644 --- a/Mesh_3/demo/Mesh_3/Mesh_function.h +++ b/Mesh_3/demo/Mesh_3/Mesh_function.h @@ -204,7 +204,7 @@ launch() /*mesher_->initialize(); #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif while ( ! mesher_->is_algorithm_done() && continue_ ) diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index ef7e7a5b96c..605c8acb4c9 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -2599,7 +2599,7 @@ rebuild_restricted_delaunay(OutdatedCells& outdated_cells, # ifdef CGAL_MESH_3_PROFILING std::cerr << std::endl << " Updating cells..."; - WallClockTimer t; + Wall_clock_timer t; size_t num_cells = c3t3_.number_of_cells_in_complex(); # endif diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h index 80f52a349ab..f5fcea26540 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h @@ -311,7 +311,7 @@ private: #ifdef CGAL_MESH_3_PROFILING std::cerr << "Computing moves..."; - WallClockTimer t; + Wall_clock_timer t; #endif @@ -690,7 +690,7 @@ operator()(int nb_iterations, Visitor visitor) running_time_.start(); #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif // Fill set containing moving vertices @@ -898,7 +898,7 @@ update_mesh(const Moves_vector& moves, #ifdef CGAL_MESH_3_PROFILING std::cerr << "Moving vertices..."; - WallClockTimer t; + Wall_clock_timer t; #endif #ifdef CGAL_LINKED_WITH_TBB diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h index cea06d3fbf6..56e6ad56eec 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h @@ -320,7 +320,7 @@ Mesher_3::refine_mesh(std::string dump_after_refine_surface_prefix) #ifdef CGAL_MESH_3_PROFILING std::cerr << "Refining facets..." << std::endl; - WallClockTimer t; + Wall_clock_timer t; #endif facets_mesher_.refine(facets_visitor_); #ifdef CGAL_MESH_3_PROFILING @@ -476,7 +476,7 @@ initialize() { #ifdef CGAL_MESH_3_PROFILING std::cerr << "Initializing... "; - WallClockTimer t; + Wall_clock_timer t; #endif //===================================== // Bounding box estimation diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h index 509be7abe19..79943874df4 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h @@ -194,7 +194,7 @@ protected: #ifdef CGAL_MESH_3_PROFILING protected: - WallClockTimer m_timer; + Wall_clock_timer m_timer; #endif public: diff --git a/Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h b/Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h index eb436c93af3..32c707f9d9e 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h +++ b/Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h @@ -28,10 +28,10 @@ // TBB timers #ifdef CGAL_LINKED_WITH_TBB #include - struct WallClockTimer + struct Wall_clock_timer { tbb::tick_count t; - WallClockTimer() + Wall_clock_timer() { t = tbb::tick_count::now(); } @@ -48,10 +48,10 @@ #else #include - struct WallClockTimer + struct Wall_clock_timer { CGAL::Real_timer t; - WallClockTimer() + Wall_clock_timer() { t.start(); } diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h b/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h index 776cd4f4796..8b6e17cb96b 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h @@ -632,7 +632,7 @@ scan_triangulation_impl() typedef typename Tr::Finite_cells_iterator Finite_cell_iterator; #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h index 1bdcc3b66d9..a58627b667a 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h @@ -882,7 +882,7 @@ scan_triangulation_impl() typedef typename Tr::Finite_facets_iterator Finite_facet_iterator; #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif #ifdef CGAL_MESH_3_VERY_VERBOSE diff --git a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h index fd3847f41ec..74fb202daf1 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h +++ b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h @@ -799,7 +799,7 @@ operator()(Visitor visitor) running_time_.start(); #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif // Build priority queue (we use one queue for all steps) diff --git a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h index 7f6a06f9ed5..cf135a4c08d 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h +++ b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h @@ -449,7 +449,7 @@ public: // methods operator()(Visitor visitor = Visitor()) { #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif Mesh_optimization_return_code ret = @@ -950,7 +950,7 @@ pump_vertices(double sliver_criterion_limit, Visitor& visitor) { #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif init(sliver_criterion_limit); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index aad9f85681d..728fc5ef8df 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -149,7 +149,7 @@ public: void compute_tangential_complex() { #ifdef CGAL_TC_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif // We need to do that because we don't want the container to copy the diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h index 427bb375010..08461059f56 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h @@ -281,7 +281,7 @@ public: #endif //CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO { #ifdef CGAL_TRIANGULATION_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif size_type n = number_of_vertices(); @@ -622,7 +622,7 @@ public: size_type n = number_of_vertices(); #ifdef CGAL_TRIANGULATION_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif // Parallel diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index cd47e98642b..8ffbe734f11 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -208,7 +208,7 @@ namespace CGAL { #endif #ifdef CGAL_TRIANGULATION_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif size_type n = number_of_vertices(); @@ -618,7 +618,7 @@ namespace CGAL { size_type n = number_of_vertices(); #ifdef CGAL_TRIANGULATION_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif // Parallel From 3cf1b89fe04d1b3eb0b6e69af1be1a8ef916136e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 17:04:21 +0200 Subject: [PATCH 108/487] Improved profiling --- .../include/CGAL/Tangential_complex.h | 4 +++- .../include/CGAL/Tangential_complex/config.h | 2 +- .../test_tangential_complex.cpp | 19 ++++++++++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 728fc5ef8df..5ba9c5db4d8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -34,7 +34,9 @@ #include #include -#include +#ifdef CGAL_TC_PROFILING +# include +#endif #include // CJTODO TEMP diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 004c5d7c309..a83560acd60 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -24,7 +24,7 @@ #include //========================= Debugging & profiling ============================= -#define CGAL_TC_PROFILING +//#define CGAL_TC_PROFILING //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 82626f91dde..5d0e344833b 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -77,6 +78,8 @@ int main() # endif #endif + Wall_clock_timer t; + //std::vector points = generate_points_on_sphere(3.0); std::vector points = generate_points_on_klein_bottle(4., 3.); @@ -84,14 +87,28 @@ int main() Kernel, INTRINSIC_DIMENSION, CGAL::Parallel_tag> tc(points.begin(), points.end()); + double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); - + double computation_time = t.elapsed(); t.reset(); + std::stringstream output_filename; output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); tc.export_to_off(off_stream); + double export_time = t.elapsed(); t.reset(); + + std::cerr << std::endl + << "================================================" << std::endl + << "Computation times (seconds): " << std::endl + << " * Tangential complex: " << init_time + computation_time + << std::endl + << " - Init + kd-tree = " << init_time << std::endl + << " - TC computation = " << computation_time << std::endl + << " * Export to OFF: " << export_time << std::endl + << "================================================" << std::endl + << std::endl; return 0; } \ No newline at end of file From 164032d1fee707470882290636b5b85e069afadc Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 17:04:54 +0200 Subject: [PATCH 109/487] Let's use some negative weights --- Tangential_complex/include/CGAL/Tangential_complex.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5ba9c5db4d8..48b3c44269f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -378,13 +378,11 @@ private: // Build a minimal triangulation in the tangent space // (we only need the star of p) //*************************************************** - - // CJTODO: replace 1000000 with something better // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(0, 0), - 1000000); + 0); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -418,7 +416,7 @@ private: FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); - FT w = 1000000 - squared_dist_to_tangent_plane; + FT w = -squared_dist_to_tangent_plane; Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( drop_w(proj_pt), w); From 8c677a8f5f89e11d675e24246043c63508ac512b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 18:45:15 +0200 Subject: [PATCH 110/487] Show inconsistencies in red --- .../include/CGAL/Tangential_complex.h | 63 +++++++++++++++++-- .../test_tangential_complex.cpp | 26 ++++++-- 2 files changed, 80 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 48b3c44269f..8d6d1a99440 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -183,7 +183,8 @@ public: #endif } - std::ostream &export_to_off(std::ostream & os) + std::ostream &export_to_off(std::ostream & os, + bool color_inconsistencies = false) { const int ambient_dim = Ambient_dimension::value; if (ambient_dim < 2) @@ -251,13 +252,32 @@ public: for ( ; it_c != it_c_end ; ++it_c) { output << Intrinsic_dimension + 1 << " "; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - output << (*it_c)->vertex(i)->data() << " "; + + if (color_inconsistencies) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + output << data << " "; + c.insert(data); + } + if (is_simplex_consistent(c)) + output << "200 200 200"; + else + output << "255 0 0"; + } + else + { + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + output << (*it_c)->vertex(i)->data() << " "; + } + output << std::endl; ++num_cells; } } - + os << "OFF \n" << m_points.size() << " " << num_cells << " " @@ -631,6 +651,41 @@ private: m_k.squared_distance_d_object()(p, projected_pt)); } + // A simplex here is a list of point indices + bool is_simplex_consistent(std::set const& simplex) + { + // Check if the simplex is in the stars of all its vertices + std::set::const_iterator it_point_idx = simplex.begin(); + // For each point + for ( ; it_point_idx != simplex.end() ; ++it_point_idx) + { + std::size_t point_idx = *it_point_idx; + Triangulation const& tr = m_triangulations[point_idx].tr(); + Tr_vertex_handle center_vh = m_triangulations[point_idx].center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + bool found = false; + for ( ; !found && it_c != it_c_end ; ++it_c) + { + std::set cell; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + cell.insert((*it_c)->vertex(i)->data()); + if (cell == simplex) + found = true; + } + + if (!found) + return false; + } + + return true; + } + private: const Kernel m_k; Points m_points; diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 5d0e344833b..ef2b13168b1 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 150; #else - const int NUM_POINTS = 50000; + const int NUM_POINTS = 10000; #endif template @@ -39,18 +39,34 @@ std::vector generate_points_on_sphere(double radius) // a = big radius, b = small radius template -std::vector generate_points_on_klein_bottle(double a, double b) +std::vector generate_points_on_klein_bottle( + double a, double b, bool uniform = false) { typedef typename CGAL::Kernel_traits::type Kernel; typedef typename Kernel::FT FT; CGAL::Random rng; + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + std::vector points; points.reserve(NUM_POINTS); for (int i = 0 ; i != NUM_POINTS ; ++i) { - FT u = rng.get_double(0, 6.2832); - FT v = rng.get_double(0, 6.2832); + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } + else + { + 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), (a + b*cos(v))*sin(u), @@ -96,7 +112,7 @@ int main() output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); - tc.export_to_off(off_stream); + tc.export_to_off(off_stream, true); double export_time = t.elapsed(); t.reset(); std::cerr << std::endl From f6a4576d19afeff9081a76a7afa7fe32e6189e4b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 2 Oct 2014 11:30:33 +0200 Subject: [PATCH 111/487] Remove the use of Kernel_traits + bug fix in OFF export --- .../include/CGAL/Tangential_complex.h | 14 ++++++++++++-- .../CGAL/Tangential_complex/Point_cloud.h | 17 ++++++++--------- .../include/CGAL/Tangential_complex/utilities.h | 1 - .../Regular_triangulation_euclidean_traits.h | 1 - 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8d6d1a99440..6be99ecce1a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -96,7 +96,7 @@ class Tangential_complex typedef std::vector Tangent_space_basis; typedef std::vector Points; - typedef Point_cloud_data_structure Points_ds; + typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; typedef typename Points_ds::INS_range INS_range; @@ -251,6 +251,9 @@ public: // For each cell for ( ; it_c != it_c_end ; ++it_c) { + if (tr.is_infinite(*it_c)) // Don't export infinite cells + continue; + output << Intrinsic_dimension + 1 << " "; if (color_inconsistencies) @@ -263,7 +266,7 @@ public: c.insert(data); } if (is_simplex_consistent(c)) - output << "200 200 200"; + output << "128 128 128"; else output << "255 0 0"; } @@ -520,6 +523,13 @@ private: Tangent_space_basis compute_tangent_space(const Point &p) const { + /*Tangent_space_basis ts; + ts.reserve(Intrinsic_dimension); + ts.push_back(Vector(1,0,0)); + ts.push_back(Vector(0,1,0)); + + return ts;*/ + // Kernel functors Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 8cc5e68fe19..ec6b6932b5d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -23,7 +23,6 @@ #include #include -#include #include #ifdef CGAL_TC_USE_NANOFLANN @@ -38,11 +37,11 @@ namespace CGAL { namespace Tangential_complex_ { // "dataset to kd-tree" adaptor class -template +template class Point_cloud_adaptator { public: - typedef typename Point_container_::value_type Point; + typedef typename Point_container_::value_type Point; typedef typename CGAL::Kernel_traits::type Kernel; typedef typename Kernel::FT FT; @@ -107,12 +106,12 @@ protected: }; -template +template class Point_cloud_data_structure { public: - typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Point_container_::value_type Point; + typedef typename K Kernel; typedef typename Kernel::FT FT; static const int AMB_DIM = Ambient_dimension::value; @@ -189,7 +188,7 @@ public: } protected: - typedef Point_cloud_adaptator Adaptor; + typedef Point_cloud_adaptator Adaptor; typedef nanoflann::KDTreeSingleIndexAdaptor< nanoflann::L2_Simple_Adaptor , Adaptor, @@ -222,12 +221,12 @@ protected: namespace CGAL { namespace Tangential_complex_ { -template +template class Point_cloud_data_structure { public: typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename K Kernel; typedef typename Kernel::FT FT; typedef CGAL::Search_traits< diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index f58ace643b3..be1a3febd20 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -22,7 +22,6 @@ #define CGAL_TC_UTILITIES_H #include -#include #include #include diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 3f5a9630a85..c5eb0248859 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -24,7 +24,6 @@ #include #include #include -#include #include From 50679b358c33e63032ad7f3a6de2bc8970d3c7d3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 2 Oct 2014 19:05:45 +0200 Subject: [PATCH 112/487] Use a boost optional for "star sphere" + export normals for 3D surface meshes --- .../include/CGAL/Tangential_complex.h | 56 ++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6be99ecce1a..be46c2ac26d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -55,6 +56,8 @@ # include #endif +//#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) + namespace CGAL { using namespace Tangential_complex_; @@ -133,6 +136,9 @@ class Tangential_complex typedef typename std::vector Tr_container; typedef typename std::vector TS_container; +#ifdef CGAL_TC_EXPORT_NORMALS + typedef typename std::vector Normals; +#endif public: /// Constructor @@ -159,6 +165,9 @@ public: // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); m_tangent_spaces.resize(m_points.size()); +#ifdef CGAL_TC_EXPORT_NORMALS + m_normals.resize(m_points.size()); +#endif #ifdef CGAL_LINKED_WITH_TBB // Parallel @@ -218,7 +227,10 @@ public: std::stringstream output; //******** VERTICES ************ - + +#ifdef CGAL_TC_EXPORT_NORMALS + Normals::const_iterator it_n = m_normals.begin(); +#endif Points::const_iterator it_p = m_points.begin(); Points::const_iterator it_p_end = m_points.end(); // For each point p @@ -229,6 +241,13 @@ public: output << (*it_p)[i] << " "; if (i == 2) output << "0"; + +#ifdef CGAL_TC_EXPORT_NORMALS + for (i = 0 ; i < num_coords ; ++i) + output << " " << (*it_n)[i]; + ++it_n; +#endif + output << std::endl; } @@ -280,6 +299,10 @@ public: ++num_cells; } } + +#ifdef CGAL_TC_EXPORT_NORMALS + os << "N"; +#endif os << "OFF \n" << m_points.size() << " " @@ -395,7 +418,11 @@ private: // Estimate the tangent space const Point ¢er_pt = m_points[i]; +#ifdef CGAL_TC_EXPORT_NORMALS + m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); +#else m_tangent_spaces[i] = compute_tangent_space(center_pt); +#endif //*************************************************** // Build a minimal triangulation in the tangent space @@ -417,7 +444,7 @@ private: // of the sphere "star sphere" centered at "center_vertex" // and which contains all the // circumspheres of the star of "center_vertex" - FT star_sphere_squared_radius = std::numeric_limits::max(); + boost::optional star_sphere_squared_radius; // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; @@ -431,7 +458,8 @@ private: { const Point &neighbor_pt = m_points[neighbor_point_idx]; - if (k_sqdist(center_pt, neighbor_pt) > star_sphere_squared_radius) + if (star_sphere_squared_radius + && k_sqdist(center_pt, neighbor_pt) > *star_sphere_squared_radius) break; Tr_point proj_pt = project_point_and_compute_weight( @@ -453,7 +481,7 @@ private: // Let's recompute star_sphere_squared_radius if (local_tr.current_dimension() >= Intrinsic_dimension) { - star_sphere_squared_radius = 0.; + star_sphere_squared_radius = 0; // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; local_tr.incident_full_cells( @@ -463,7 +491,7 @@ private: { if (local_tr.is_infinite(cell)) { - star_sphere_squared_radius = std::numeric_limits::max(); + star_sphere_squared_radius = boost::none; break; } else @@ -500,7 +528,8 @@ private: proj_pts.begin(), proj_pts.end()); FT sq_circumdiam = 4.*sqdist(c, proj_pts[0]); - if (sq_circumdiam > star_sphere_squared_radius) + if (!star_sphere_squared_radius + || sq_circumdiam > *star_sphere_squared_radius) star_sphere_squared_radius = sq_circumdiam; } } @@ -521,7 +550,11 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } - Tangent_space_basis compute_tangent_space(const Point &p) const + Tangent_space_basis compute_tangent_space(const Point &p +#ifdef CGAL_TC_EXPORT_NORMALS + , Vector *p_normal +#endif + ) const { /*Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); @@ -567,6 +600,12 @@ private: eig.eigenvectors().col(i).data(), eig.eigenvectors().col(i).data() + amb_dim)); } +#ifdef CGAL_TC_EXPORT_NORMALS + *p_normal = constr_vec( + amb_dim, + eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data(), + eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data() + amb_dim); +#endif //************************************************************************* @@ -703,6 +742,9 @@ private: TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations // and their center vertex +#ifdef CGAL_TC_EXPORT_NORMALS + Normals m_normals; +#endif }; // /class Tangential_complex From 4c6c0be37f4101cfca11718470bf610bb1ea54d7 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 13 Oct 2014 17:11:43 +0200 Subject: [PATCH 113/487] Unofficial Epeck_d (exact and very slow) for testing purposes. --- NewKernel_d/include/CGAL/Epeck_d.h | 53 ++++++++++++++++++++++++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 36 +++++++++------- 2 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 NewKernel_d/include/CGAL/Epeck_d.h diff --git a/NewKernel_d/include/CGAL/Epeck_d.h b/NewKernel_d/include/CGAL/Epeck_d.h new file mode 100644 index 00000000000..52bce84ca3f --- /dev/null +++ b/NewKernel_d/include/CGAL/Epeck_d.h @@ -0,0 +1,53 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_EPECK_D_H +#define CGAL_EPECK_D_H +#include +#include +#include +#include + + +namespace CGAL { +#define CGAL_BASE \ + Cartesian_base_d::Type, Dim> +template +struct Epeck_d_help1 +: CGAL_BASE +{ + CGAL_CONSTEXPR Epeck_d_help1(){} + CGAL_CONSTEXPR Epeck_d_help1(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE +#define CGAL_BASE \ + Kernel_d_interface< \ + Cartesian_wrap< \ + Epeck_d_help1, \ + Epeck_d > > +template +struct Epeck_d +: CGAL_BASE +{ + CGAL_CONSTEXPR Epeck_d(){} + CGAL_CONSTEXPR Epeck_d(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE +} +#endif diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 0635bc4cc3f..01c63d26ac7 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -13,6 +13,7 @@ #include #include #include +#include //typedef CGAL::Cartesian_base_d > K0; //typedef CGAL::Cartesian_base_d > KA; @@ -185,11 +186,12 @@ void test2(){ CGAL_USE(cli); CGAL_USE(cr); CGAL_USE(cib); + using std::abs; P a=cp(3,4); assert(pd(a)==2); assert(pv(a)[1]==4); P b=vp(cv(5,6,7)); - assert(fabs(b[0]-5./7)<.0001); + assert(abs(b[0]-5./7)<.0001); assert(lc(b,a,1)); assert(!lc(a,b,0)); int rr[]={3,5,2}; @@ -203,8 +205,8 @@ void test2(){ assert(cl(a,c)==CGAL::SMALLER); assert(ll(b,c)); assert(cl(c,b)==CGAL::LARGER); - assert(fabs(m(a,c)[0]-3)<.0001); - assert(fabs(m(a,c)[1]-4.5)<.0001); + assert(abs(m(a,c)[0]-3)<.0001); + assert(abs(m(a,c)[1]-4.5)<.0001); P d=cp(r,r+3,CGAL::Homogeneous_tag()); S s=cs(c,d); std::cout << cc(a,1) << std::endl; @@ -253,9 +255,9 @@ void test2(){ assert(v.size()==1); assert(lr(tab3+0,tab3+2)==1); H h=ch(tab2+1,tab2+3); - assert(fabs(va(h,x2)-1)<.0001); - assert(fabs(va(h,x3)-1)<.0001); - assert(fabs(va(h,x1)+1)<.0001); + assert(abs(va(h,x2)-1)<.0001); + assert(abs(va(h,x3)-1)<.0001); + assert(abs(va(h,x1)+1)<.0001); H h2=ch(tab2+1,tab2+3,x1,CGAL::ON_POSITIVE_SIDE); assert(hops(h2,x1)); assert(os(h2,x1)==CGAL::ON_POSITIVE_SIDE); @@ -312,20 +314,23 @@ void test2(){ Sp sp = csp(tabz+0,tabz+3); P cent0=cos(sp); P cent1=cos(tabz+0,tabz+3); - assert(fabs(cent0[0]-2)<.0001); - assert(fabs(cent0[1]+3)<.0001); - assert(fabs(cent1[0]-2)<.0001); - assert(fabs(cent1[1]+3)<.0001); - assert(fabs(sp.squared_radius()-25)<.0001); + assert(abs(cent0[0]-2)<.0001); + assert(abs(cent0[1]+3)<.0001); + assert(abs(cent1[0]-2)<.0001); + assert(abs(cent1[1]+3)<.0001); + assert(abs(sp.squared_radius()-25)<.0001); +#if 1 + // Fails for an exact kernel P psp0=ps(sp,0); P psp1=ps(sp,1); P psp2=ps(sp,2); assert(!ed(psp0,psp1)); assert(!ed(psp0,psp2)); assert(!ed(psp2,psp1)); - assert(fabs(sd(cent0,psp0)-25)<.0001); - assert(fabs(sd(cent0,psp1)-25)<.0001); - assert(fabs(sd(cent0,psp2)-25)<.0001); + assert(abs(sd(cent0,psp0)-25)<.0001); + assert(abs(sd(cent0,psp1)-25)<.0001); + assert(abs(sd(cent0,psp2)-25)<.0001); +#endif Sp un1; CGAL_USE(un1); H un2; CGAL_USE(un2); S un3; CGAL_USE(un3); @@ -418,6 +423,7 @@ void test3(){ SD sd Kinit(squared_distance_d_object); PD pd Kinit(point_dimension_d_object); AI ai Kinit(affinely_independent_d_object); + using std::abs; P a; // Triangulation needs this :-( a=cp(2,3,4); assert(pd(a)==3); @@ -441,7 +447,7 @@ void test3(){ std::cout << *i << ' '; std::cout << '\n'; P e=cp(-2,3,0); - assert(fabs(sd(e,a)-32)<.0001); + assert(abs(sd(e,a)-32)<.0001); P tab[]={a,b,c,d,e}; std::cout << po (&tab[0],tab+4) << ' '; std::cout << sos(&tab[0],tab+5) << ' '; From b5bee8fbfc95a9ea6581c909ed419b3224fa11e6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Oct 2014 16:08:11 +0200 Subject: [PATCH 114/487] Fix a bug in the computation of the weights + better export and debug code + remove the uses of Ambient_dimension + improved test + Comments clean-up --- .../include/CGAL/Tangential_complex.h | 404 +++++++++++++----- .../CGAL/Tangential_complex/Point_cloud.h | 10 +- .../include/CGAL/Tangential_complex/config.h | 1 + .../CGAL/Tangential_complex/utilities.h | 17 +- .../test_tangential_complex.cpp | 126 ++++-- 5 files changed, 409 insertions(+), 149 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index be46c2ac26d..909ee277852 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include #ifdef CGAL_TC_PROFILING # include @@ -47,10 +49,12 @@ #include #include +#include #include #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -141,15 +145,12 @@ class Tangential_complex #endif public: - /// Constructor - Tangential_complex(const Kernel &k = Kernel()) - : m_k(k){} /// Constructor for a range of points template Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), m_points(first, last), m_points_ds(m_points, k) {} + : m_k(k), m_points(first, last), m_points_ds(m_points) {} /// Destructor ~Tangential_complex() {} @@ -173,7 +174,6 @@ public: // Parallel if (boost::is_convertible::value) { - // Apply moves in triangulation tbb::parallel_for(tbb::blocked_range(0, m_points.size()), Compute_tangent_triangulation(*this) ); @@ -192,10 +192,16 @@ public: #endif } - std::ostream &export_to_off(std::ostream & os, - bool color_inconsistencies = false) + std::ostream &export_to_off( + std::ostream & os, + bool color_inconsistencies = false, + std::set > const* excluded_simplices = NULL, + bool show_excluded_vertices_in_color = false) { - const int ambient_dim = Ambient_dimension::value; + if (m_points.empty()) + return os; + + const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); if (ambient_dim < 2) { std::cerr << "Error: export_to_off => ambient dimension should be >= 2." @@ -211,8 +217,6 @@ public: << std::endl; } - int num_coords = min(ambient_dim, 3); - if (Intrinsic_dimension < 1 || Intrinsic_dimension > 3) { std::cerr << "Error: export_to_off => intrinsic dimension should be " @@ -225,80 +229,11 @@ public: } std::stringstream output; - - //******** VERTICES ************ - -#ifdef CGAL_TC_EXPORT_NORMALS - Normals::const_iterator it_n = m_normals.begin(); -#endif - Points::const_iterator it_p = m_points.begin(); - Points::const_iterator it_p_end = m_points.end(); - // For each point p - for ( ; it_p != it_p_end ; ++it_p) - { - int i = 0; - for ( ; i < num_coords ; ++i) - output << (*it_p)[i] << " "; - if (i == 2) - output << "0"; - -#ifdef CGAL_TC_EXPORT_NORMALS - for (i = 0 ; i < num_coords ; ++i) - output << " " << (*it_n)[i]; - ++it_n; -#endif - - output << std::endl; - } - - //******** CELLS ************ - - std::size_t num_cells = 0; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); - // For each triangulation - for ( ; it_tr != it_tr_end ; ++it_tr) - { - Triangulation const& tr = it_tr->tr(); - Tr_vertex_handle center_vh = it_tr->center_vertex(); - - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); - // For each cell - for ( ; it_c != it_c_end ; ++it_c) - { - if (tr.is_infinite(*it_c)) // Don't export infinite cells - continue; - - output << Intrinsic_dimension + 1 << " "; - - if (color_inconsistencies) - { - std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - { - std::size_t data = (*it_c)->vertex(i)->data(); - output << data << " "; - c.insert(data); - } - if (is_simplex_consistent(c)) - output << "128 128 128"; - else - output << "255 0 0"; - } - else - { - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - output << (*it_c)->vertex(i)->data() << " "; - } - - output << std::endl; - ++num_cells; - } - } + std::size_t num_cells, num_vertices; + export_vertices_to_off(output, num_vertices); + export_simplices_to_off( + output, num_cells, color_inconsistencies, + excluded_simplices, show_excluded_vertices_in_color); #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; @@ -312,6 +247,121 @@ public: return os; } + + bool check_if_all_simplices_are_in_the_ambient_delaunay( + std::set > * incorrect_simplices = NULL) + { + if (m_points.empty()) + return true; + + const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); + typedef typename Delaunay_triangulation< + Kernel, + Triangulation_data_structure + < + Kernel::Dimension, + Triangulation_vertex + > + > DT; + typedef typename DT::Vertex_handle DT_VH; + typedef typename DT::Finite_full_cell_const_iterator FFC_it; + typedef std::set Indexed_simplex; + + //------------------------------------------------------------------------- + // Build the ambient Delaunay triangulation + // Then save its simplices into "amb_dt_simplices" + //------------------------------------------------------------------------- + + DT ambient_dt(ambient_dim); + std::size_t i = 0; + for (Point const& p : m_points) // CJTODO C++11 + { + DT_VH vh = ambient_dt.insert(p); + vh->data() = i; + ++i; + } + + std::set amb_dt_simplices; + + for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; + cit != ambient_dt.finite_full_cells_end() ; ++cit ) + { + CGAL::Combination_enumerator combi( + Intrinsic_dimension + 1, 0, ambient_dim + 1); + + for ( ; !combi.finished() ; ++combi) + { + Indexed_simplex simplex; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + simplex.insert(cit.base()->vertex(combi[i])->data()); + + amb_dt_simplices.insert(simplex); + } + } + + //------------------------------------------------------------------------- + // Parse the TC and save its simplices into "stars_simplices" + //------------------------------------------------------------------------- + + std::set stars_simplices; + + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + if (tr.is_infinite(*it_c)) + { + std::cerr << "Warning: infinite cell in star" << std::endl; + continue; + } + Indexed_simplex simplex; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + simplex.insert((*it_c)->vertex(i)->data()); + + stars_simplices.insert(simplex); + } + } + + //------------------------------------------------------------------------- + // Check if simplices of "stars_simplices" are all in "amb_dt_simplices" + //------------------------------------------------------------------------- + + std::set diff; + if (!incorrect_simplices) + incorrect_simplices = &diff; + set_difference(stars_simplices.begin(), stars_simplices.end(), + amb_dt_simplices.begin(), amb_dt_simplices.end(), + std::inserter(*incorrect_simplices, + incorrect_simplices->begin()) ); + + if (!incorrect_simplices->empty()) + { + std::cerr + << "ERROR check_if_all_simplices_are_in_the_ambient_delaunay:" + << std::endl + << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << std::endl + << " Number of unique simplices in TC stars: " << stars_simplices.size() + << std::endl + << " Number of wrong simplices: " << incorrect_simplices->size() + << std::endl; + return false; + } + else + return true; + } private: @@ -556,13 +606,6 @@ private: #endif ) const { - /*Tangent_space_basis ts; - ts.reserve(Intrinsic_dimension); - ts.push_back(Vector(1,0,0)); - ts.push_back(Vector(0,1,0)); - - return ts;*/ - // Kernel functors Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); @@ -574,8 +617,8 @@ private: p, NUM_POINTS_FOR_PCA, false); //******************************* PCA ************************************* - - const int amb_dim = Ambient_dimension::value; + + const int amb_dim = m_k.point_dimension_d_object()(p); // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); KNS_iterator nn_it = kns_range.begin(); @@ -584,7 +627,7 @@ private: ++j, ++nn_it) { for (int i = 0 ; i < amb_dim ; ++i) - mat_points(j, i) = m_points[nn_it->first][i]; // CJTODO: Use kernel functor + mat_points(j, i) = CGAL::to_double(m_points[nn_it->first][i]); // CJTODO: Use kernel functor } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -610,7 +653,7 @@ private: //************************************************************************* //Vector n = m_k.point_to_vector_d_object()(p); - //n = scaled_vec(n, 1./sqrt(sqlen(n))); + //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; return compute_gram_schmidt_basis(ts, m_k); @@ -623,18 +666,20 @@ private: p[0] * t1[1] - p[1] * t1[0]); // Normalize t1 and t2 - Kernel::Scaled_vector_d scale = m_k.scaled_vector_d_object(); + Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); - ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); - ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); + ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); + ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); - return ts; + return ts;*/ + /* // Alternative code (to be used later) //Vector n = m_k.point_to_vector_d_object()(p); - //n = scaled_vec(n, 1./sqrt(sqlen(n))); + //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //Vector t1(12., 15., 65.); //Vector t2(32., 5., 85.); //Tangent_space_basis ts; @@ -673,29 +718,43 @@ private: Tr_point project_point_and_compute_weight( const Point &p, const Point &origin, const Tangent_space_basis &ts) const { + const int point_dim = m_k.point_dimension_d_object()(p); Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); + Kernel::Construct_cartesian_const_iterator_d ccci = + m_k.construct_cartesian_const_iterator_d_object(); + + Vector v = diff_points(p, origin); std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); // CJTODO: use kernel functors? + std::vector p_proj(ccci(origin), ccci(origin, 0)); coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { // Compute the inner product p * ts[i] - Vector v = diff_points(p, origin); FT coord = inner_pdct(v, ts[i]); coords.push_back(coord); // p_proj += coord * v; - for (int j = 0 ; j < Ambient_dimension::value ; ++j) - p_proj[i] += coord * ts[i][j]; + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += coord * ts[i][j]; } - Point projected_pt(Ambient_dimension::value, - p_proj.begin(), p_proj.end()); - return Tr_point( + // CJTODO TEMP: test it + /*Kernel::Construct_vector_d c_vec = m_k.construct_vector_d_object(); + Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + Point proj_pt = origin; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + Vector base_i = c_vec(point_dim, ts[i].begin(), ts[i].end()); + FT coef = inner_pdct(v, base_i); + proj_pt = proj_pt + scaled_vec(base_i, coef); + }*/ + + Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); + return Tr_point( // CJTODO: use kernel constructions Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), m_k.squared_distance_d_object()(p, projected_pt)); } @@ -735,6 +794,137 @@ private: return true; } + std::ostream &export_vertices_to_off( + std::ostream & os, std::size_t &num_vertices) + { + if (m_points.empty()) + { + num_vertices = 0; + return os; + } + + const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); + int num_coords = min(ambient_dim, 3); +#ifdef CGAL_TC_EXPORT_NORMALS + Normals::const_iterator it_n = m_normals.begin(); +#endif + Points::const_iterator it_p = m_points.begin(); + Points::const_iterator it_p_end = m_points.end(); + // For each point p + for ( ; it_p != it_p_end ; ++it_p) + { + int i = 0; + for ( ; i < num_coords ; ++i) + os << CGAL::to_double((*it_p)[i]) << " "; // CJTODO: use kernel functors, not [] + if (i == 2) + os << "0"; + +#ifdef CGAL_TC_EXPORT_NORMALS + for (i = 0 ; i < num_coords ; ++i) + os << " " << CGAL::to_double((*it_n)[i]); // CJTODO: use kernel functors, not [] + ++it_n; +#endif + + os << std::endl; + } + + num_vertices = m_points.size(); + return os; + } + + std::ostream &export_simplices_to_off( + std::ostream & os, std::size_t &num_cells, + bool color_inconsistencies = false, + std::set > const* excluded_simplices = NULL, + bool show_excluded_vertices_in_color = false) + { + num_cells = 0; + std::size_t num_inconsistent_simplices = 0; + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + + // Color for this star + std::stringstream color; + //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; + color << 128 << " " << 128 << " " << 128; + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + if (tr.is_infinite(*it_c)) // Don't export infinite cells + continue; + + if (color_inconsistencies || excluded_simplices) + { + std::set c; + std::stringstream sstr_c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + sstr_c << data << " "; + c.insert(data); + } + + bool excluded = + (excluded_simplices + && excluded_simplices->find(c) != excluded_simplices->end()); + + if (!excluded) + { + os << Intrinsic_dimension + 1 << " " << sstr_c.str() << " "; + if (color_inconsistencies && is_simplex_consistent(c)) + os << color.str(); + else + { + os << "255 0 0"; + ++num_inconsistent_simplices; + } + ++num_cells; + } + else if (show_excluded_vertices_in_color) + { + os << Intrinsic_dimension + 1 << " " + << sstr_c.str() << " " + << "0 0 255"; + ++num_cells; + } + } + else + { + os << Intrinsic_dimension + 1 << " "; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + os << (*it_c)->vertex(i)->data() << " "; + ++num_cells; + } + + os << std::endl; + } + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "================================================" << std::endl + << "Export to OFF:\n" + << " * Total number of simplices in stars (incl. duplicates): " + << num_cells << std::endl + << " * Number of inconsistent simplices in stars (incl. duplicates): " + << num_inconsistent_simplices << std::endl + << "================================================" << std::endl; +#endif + + return os; + } + private: const Kernel m_k; Points m_points; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index ec6b6932b5d..a8f53b8c24c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -114,7 +114,7 @@ public: typedef typename K Kernel; typedef typename Kernel::FT FT; - static const int AMB_DIM = Ambient_dimension::value; + static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar /// Constructor Point_cloud_data_structure(Point_container_ &points, Kernel const& k) @@ -249,10 +249,10 @@ public: typedef typename Incremental_neighbor_search::iterator INS_iterator; typedef Incremental_neighbor_search INS_range; - static const int AMB_DIM = Ambient_dimension::value; + static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar /// Constructor - Point_cloud_data_structure(Point_container_ const& points, Kernel const& k) + Point_cloud_data_structure(Point_container_ const& points) : m_points(points), m_tree( boost::counting_iterator(0), @@ -284,7 +284,7 @@ public: m_tree, sp, k, - FT(0.0), + FT(0), true, Distance_adapter >( (Point*)&(m_points[0])), @@ -301,7 +301,7 @@ public: Incremental_neighbor_search search( m_tree, sp, - FT(0.0), + FT(0), true, Distance_adapter >( (Point*)&(m_points[0])) ); diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index a83560acd60..f6e830ef9f8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -25,6 +25,7 @@ //========================= Debugging & profiling ============================= //#define CGAL_TC_PROFILING +#define CGAL_TC_VERBOSE //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index be1a3febd20..bcf66a6dda8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -35,17 +35,17 @@ namespace Tangential_complex_ { std::vector const& input_basis, K const& kernel) { - typedef typename K::Vector_d Vector; - typedef std::vector Basis; - const int D = Ambient_dimension::value; + typedef typename K::FT FT; + typedef typename K::Vector_d Vector; + typedef std::vector Basis; + + const int D = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar // Kernel functors K::Squared_length_d sqlen = kernel.squared_length_d_object(); K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); - //K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); - //K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); - Get_functor::type inner_pdct(kernel); // CJTODO TEMP - Get_functor::type diff_vec(kernel); + K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); + K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); Basis output_basis; @@ -63,7 +63,8 @@ namespace Tangential_complex_ { u = diff_vec(u, u_proj); } - output_basis.push_back(scaled_vec(u, 1./CGAL::sqrt(sqlen(u)))); + output_basis.push_back( + scaled_vec(u, FT(1)/CGAL::sqrt(sqlen(u)))); } return output_basis; diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index ef2b13168b1..5817608f200 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -21,11 +21,28 @@ #endif #ifdef _DEBUG - const int NUM_POINTS = 150; + const int NUM_POINTS = 6; #else - const int NUM_POINTS = 10000; + const int NUM_POINTS = 50000; #endif +template +std::vector generate_points_on_plane() +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + 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)); + } + return points; +} + template std::vector generate_points_on_sphere(double radius) { @@ -39,7 +56,46 @@ std::vector generate_points_on_sphere(double radius) // a = big radius, b = small radius template -std::vector generate_points_on_klein_bottle( +std::vector generate_points_on_klein_bottle_3D( + double a, double b, bool uniform = false) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } + else + { + u = rng.get_double(0, 6.2832); + 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()( + (a + b*tmp)*cos(u), + (a + b*tmp)*sin(u), + b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); + } + return points; +} + +// a = big radius, b = small radius +template +std::vector generate_points_on_klein_bottle_4D( double a, double b, bool uniform = false) { typedef typename CGAL::Kernel_traits::type Kernel; @@ -94,37 +150,49 @@ int main() # endif #endif - Wall_clock_timer t; + int i = 0; + bool stop = false; + //for ( ; !stop ; ++i) + { + Wall_clock_timer t; + CGAL::default_random = CGAL::Random(i); + std::cerr << "Random seed = " << i << std::endl; + + //std::vector points = generate_points_on_plane(); + //std::vector points = generate_points_on_sphere(3.0); + //std::vector points = generate_points_on_klein_bottle_3D(4., 3.); + std::vector points = generate_points_on_klein_bottle_4D(4., 3.); - //std::vector points = generate_points_on_sphere(3.0); - std::vector points = generate_points_on_klein_bottle(4., 3.); + CGAL::Tangential_complex< + Kernel, + INTRINSIC_DIMENSION, + CGAL::Parallel_tag> tc(points.begin(), points.end()); + double init_time = t.elapsed(); t.reset(); - CGAL::Tangential_complex< - Kernel, - INTRINSIC_DIMENSION, - CGAL::Parallel_tag> tc(points.begin(), points.end()); - double init_time = t.elapsed(); t.reset(); + tc.compute_tangential_complex(); + double computation_time = t.elapsed(); t.reset(); - tc.compute_tangential_complex(); - double computation_time = t.elapsed(); t.reset(); + std::set > incorrect_simplices; + //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); - std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION - << "_in_R" << AMBIENT_DIMENSION << ".off"; - std::ofstream off_stream(output_filename.str()); - tc.export_to_off(off_stream, true); - double export_time = t.elapsed(); t.reset(); + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + double export_time = t.elapsed(); t.reset(); - std::cerr << std::endl - << "================================================" << std::endl - << "Computation times (seconds): " << std::endl - << " * Tangential complex: " << init_time + computation_time - << std::endl - << " - Init + kd-tree = " << init_time << std::endl - << " - TC computation = " << computation_time << std::endl - << " * Export to OFF: " << export_time << std::endl - << "================================================" << std::endl - << std::endl; + std::cerr << std::endl + << "================================================" << std::endl + << "Computation times (seconds): " << std::endl + << " * Tangential complex: " << init_time + computation_time + << std::endl + << " - Init + kd-tree = " << init_time << std::endl + << " - TC computation = " << computation_time << std::endl + << " * Export to OFF: " << export_time << std::endl + << "================================================" << std::endl + << std::endl; + } return 0; } \ No newline at end of file From 57690e3a908b59f2837322185c55fddb3d4346c2 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 14 Oct 2014 16:15:33 +0200 Subject: [PATCH 115/487] Translated_point_d --- NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h | 2 ++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index dcbea88278c..cd8269f07da 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -73,6 +73,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type In_flat_power_test_d; typedef typename Get_functor::type Point_to_vector_d; typedef typename Get_functor::type Vector_to_point_d; + typedef typename Get_functor::type Translated_point_d; typedef typename Get_functor::type Scaled_vector_d; typedef typename Get_functor::type Difference_of_vectors_d; typedef typename Get_functor::type Difference_of_points_d; @@ -184,6 +185,7 @@ template struct Kernel_d_interface : public Base_ { In_flat_power_test_d in_flat_power_test_d_object()const{ return In_flat_power_test_d(*this); } Point_to_vector_d point_to_vector_d_object()const{ return Point_to_vector_d(*this); } Vector_to_point_d vector_to_point_d_object()const{ return Vector_to_point_d(*this); } + Translated_point_d translated_point_d_object()const{ return Translated_point_d(*this); } Scaled_vector_d scaled_vector_d_object()const{ return Scaled_vector_d(*this); } Difference_of_vectors_d difference_of_vectors_d_object()const{ return Difference_of_vectors_d(*this); } Difference_of_points_d difference_of_points_d_object()const{ return Difference_of_points_d(*this); } diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 01c63d26ac7..c98fad5d9cd 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -121,6 +121,7 @@ void test2(){ typedef typename K1::Scalar_product_d SP; typedef typename K1::Difference_of_vectors_d DV; typedef typename K1::Difference_of_points_d DP; + typedef typename K1::Translated_point_d TP; CGAL_USE_TYPE(AT); CGAL_USE_TYPE(D); @@ -178,6 +179,7 @@ void test2(){ SP spr Kinit(scalar_product_d_object); DV dv Kinit(difference_of_vectors_d_object); DP dp Kinit(difference_of_points_d_object); + TP tp Kinit(translated_point_d_object); CGAL_USE(bc); CGAL_USE(pol); @@ -331,6 +333,8 @@ void test2(){ assert(abs(sd(cent0,psp1)-25)<.0001); assert(abs(sd(cent0,psp2)-25)<.0001); #endif + P x2py1 = tp(x2,y1); + assert(x2py1[1]==-2); Sp un1; CGAL_USE(un1); H un2; CGAL_USE(un2); S un3; CGAL_USE(un3); From a1d9b2477ef225d380ecf1e4f60ad36004ac6165 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Oct 2014 17:24:13 +0200 Subject: [PATCH 116/487] Missing "typename"s + better use of the kernel --- .../include/CGAL/Tangential_complex.h | 81 ++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 909ee277852..fef6c48845f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -259,7 +259,7 @@ public: Kernel, Triangulation_data_structure < - Kernel::Dimension, + typename Kernel::Dimension, Triangulation_vertex > > DT; @@ -373,7 +373,8 @@ private: bool operator()(Point const& p1, Point const& p2) { - Kernel::Squared_distance_d sqdist = m_k.squared_distance_d_object(); + typename Kernel::Squared_distance_d sqdist = + m_k.squared_distance_d_object(); return sqdist(p1, m_ref) < sqdist(p2, m_ref); } @@ -453,9 +454,9 @@ private: Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects - Kernel::Difference_of_points_d k_diff_pts = + typename Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - Kernel::Squared_distance_d k_sqdist = + typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); // Triangulation's traits functor & objects @@ -481,7 +482,7 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(0, 0), + local_tr_traits.construct_point_d_object()(Intrinsic_dimension), 0); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -513,7 +514,7 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, center_pt, m_tangent_spaces[i]); + neighbor_pt, center_pt, m_tangent_spaces[i], local_tr_traits); FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); @@ -607,11 +608,18 @@ private: ) const { // Kernel functors - Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); - Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); + typename Kernel::Construct_vector_d constr_vec = + m_k.construct_vector_d_object(); + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename Kernel::Squared_length_d sqlen = + m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Scalar_product_d inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Difference_of_vectors_d diff_vec = + m_k.difference_of_vectors_d_object(); KNS_range kns_range = m_points_ds.query_ANN( p, NUM_POINTS_FOR_PCA, false); @@ -627,7 +635,7 @@ private: ++j, ++nn_it) { for (int i = 0 ; i < amb_dim ; ++i) - mat_points(j, i) = CGAL::to_double(m_points[nn_it->first][i]); // CJTODO: Use kernel functor + mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -666,8 +674,8 @@ private: p[0] * t1[1] - p[1] * t1[0]); // Normalize t1 and t2 - Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); @@ -695,8 +703,9 @@ private: Tr_bare_point project_point(const Point &p, const Point &origin, const Tangent_space_basis &ts) const { - Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - Kernel::Difference_of_points_d diff_points = + typename Kernel::Scalar_product_d inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); std::vector coords; @@ -716,13 +725,15 @@ private: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p Tr_point project_point_and_compute_weight( - const Point &p, const Point &origin, const Tangent_space_basis &ts) const + const Point &p, const Point &origin, const Tangent_space_basis &ts, + const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); - Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - Kernel::Difference_of_points_d diff_points = + typename Kernel::Scalar_product_d inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); - Kernel::Construct_cartesian_const_iterator_d ccci = + typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); Vector v = diff_points(p, origin); @@ -742,21 +753,14 @@ private: p_proj[j] += coord * ts[i][j]; } - // CJTODO TEMP: test it - /*Kernel::Construct_vector_d c_vec = m_k.construct_vector_d_object(); - Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - Point proj_pt = origin; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - Vector base_i = c_vec(point_dim, ts[i].begin(), ts[i].end()); - FT coef = inner_pdct(v, base_i); - proj_pt = proj_pt + scaled_vec(base_i, coef); - }*/ - Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); - return Tr_point( // CJTODO: use kernel constructions - Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), - m_k.squared_distance_d_object()(p, projected_pt)); + + return tr_traits.construct_weighted_point_d_object() + ( + tr_traits.construct_point_d_object()( + Intrinsic_dimension, coords.begin(), coords.end()), + m_k.squared_distance_d_object()(p, projected_pt) + ); } // A simplex here is a list of point indices @@ -804,6 +808,11 @@ private: } const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); + + // Kernel functors + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + int num_coords = min(ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS Normals::const_iterator it_n = m_normals.begin(); @@ -815,13 +824,13 @@ private: { int i = 0; for ( ; i < num_coords ; ++i) - os << CGAL::to_double((*it_p)[i]) << " "; // CJTODO: use kernel functors, not [] + os << CGAL::to_double(coord(*it_p, i)) << " "; if (i == 2) os << "0"; #ifdef CGAL_TC_EXPORT_NORMALS for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double((*it_n)[i]); // CJTODO: use kernel functors, not [] + os << " " << CGAL::to_double(coord(*it_n, i)); ++it_n; #endif From dc209b8e3427831c549e3befeac4186fe9ae2332 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Oct 2014 17:25:51 +0200 Subject: [PATCH 117/487] Clean-up comment --- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 9ad874311a4..b5174b0f698 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -1036,7 +1036,7 @@ Regular_triangulation } else { - Orientation_d ori = geom_traits().orientation_d_object(); // CJTODO: create member variables for this? + Orientation_d ori = geom_traits().orientation_d_object(); Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); return c(s); From 5cf4767597e4aef1a5cb5c3b6042f67d21bb42dd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Oct 2014 17:56:45 +0200 Subject: [PATCH 118/487] Add ORIGIN to construct a (0,... 0) point --- Tangential_complex/include/CGAL/Tangential_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fef6c48845f..3c229c83239 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -482,7 +482,7 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(Intrinsic_dimension), + local_tr_traits.construct_point_d_object()(Intrinsic_dimension, ORIGIN), 0); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -509,7 +509,7 @@ private: { const Point &neighbor_pt = m_points[neighbor_point_idx]; - if (star_sphere_squared_radius + if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) > *star_sphere_squared_radius) break; From 584e6255c917690d06a58ac51e0524df5f192a23 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 15:36:54 +0200 Subject: [PATCH 119/487] Add function "number_of_inconsistent_simplices" --- .../include/CGAL/Tangential_complex.h | 72 ++++++++++++++++--- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3c229c83239..473aee33c72 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -191,7 +191,57 @@ public: << " seconds." << std::endl; #endif } + + // Return a pair + std::pair number_of_inconsistent_simplices() + { + std::size_t num_simplices = 0; + std::size_t num_inconsistent_simplices = 0; + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + c.insert(data); + } + + if (!is_simplex_consistent(c)) + ++num_inconsistent_simplices; + ++num_simplices; + } + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "================================================" << std::endl + << "Inconsistencies:\n" + << " * Total number of simplices in stars (incl. duplicates): " + << num_simplices << std::endl + << " * Number of inconsistent simplices in stars (incl. duplicates): " + << num_inconsistent_simplices << std::endl + << " * Percentage of inconsistencies: " + << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl + << "================================================" << std::endl; +#endif + + return std::make_pair(num_simplices, num_inconsistent_simplices); + } + std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, @@ -229,10 +279,10 @@ public: } std::stringstream output; - std::size_t num_cells, num_vertices; + std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); export_simplices_to_off( - output, num_cells, color_inconsistencies, + output, num_simplices, color_inconsistencies, excluded_simplices, show_excluded_vertices_in_color); #ifdef CGAL_TC_EXPORT_NORMALS @@ -241,7 +291,7 @@ public: os << "OFF \n" << m_points.size() << " " - << num_cells << " " + << num_simplices << " " << "0 \n" << output.str(); @@ -840,14 +890,14 @@ private: num_vertices = m_points.size(); return os; } - + std::ostream &export_simplices_to_off( - std::ostream & os, std::size_t &num_cells, + std::ostream & os, std::size_t &num_simplices, bool color_inconsistencies = false, std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) { - num_cells = 0; + num_simplices = 0; std::size_t num_inconsistent_simplices = 0; Tr_container::const_iterator it_tr = m_triangulations.begin(); Tr_container::const_iterator it_tr_end = m_triangulations.end(); @@ -898,14 +948,14 @@ private: os << "255 0 0"; ++num_inconsistent_simplices; } - ++num_cells; + ++num_simplices; } else if (show_excluded_vertices_in_color) { os << Intrinsic_dimension + 1 << " " << sstr_c.str() << " " << "0 0 255"; - ++num_cells; + ++num_simplices; } } else @@ -913,7 +963,7 @@ private: os << Intrinsic_dimension + 1 << " "; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) os << (*it_c)->vertex(i)->data() << " "; - ++num_cells; + ++num_simplices; } os << std::endl; @@ -925,9 +975,11 @@ private: << "================================================" << std::endl << "Export to OFF:\n" << " * Total number of simplices in stars (incl. duplicates): " - << num_cells << std::endl + << num_simplices << std::endl << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl + << " * Percentage of inconsistencies: " + << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl << "================================================" << std::endl; #endif From 13b9f6b254141fdc4e445d197dc8db45f601df4e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 18:17:38 +0200 Subject: [PATCH 120/487] Code reorganization + function to generate points on n-spheres --- .../test_tangential_complex.cpp | 132 ++------------- .../test/Tangential_complex/test_utilities.h | 152 ++++++++++++++++++ 2 files changed, 168 insertions(+), 116 deletions(-) create mode 100644 Tangential_complex/test/Tangential_complex/test_utilities.h diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 5817608f200..1123f9a81f6 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -6,9 +6,10 @@ # define TBB_USE_THREADING_TOOL #endif +#include "test_utilities.h" + #include #include -#include #include #include #include @@ -21,121 +22,15 @@ #endif #ifdef _DEBUG - const int NUM_POINTS = 6; + const int NUM_POINTS = 50; #else - const int NUM_POINTS = 50000; + const int NUM_POINTS = 500; #endif -template -std::vector generate_points_on_plane() -{ - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - CGAL::Random rng; - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - { - 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)); - } - return points; -} - -template -std::vector generate_points_on_sphere(double radius) -{ - CGAL::Random_points_on_sphere_3 generator(radius); - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - points.push_back(*generator++); - return points; -} - -// a = big radius, b = small radius -template -std::vector generate_points_on_klein_bottle_3D( - double a, double b, bool uniform = false) -{ - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - CGAL::Random rng; - - // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; - - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - { - FT u, v; - if (uniform) - { - int k1 = i / num_lines; - int k2 = i % num_lines; - u = 6.2832 * k1 / num_lines; - v = 6.2832 * k2 / num_lines; - } - else - { - u = rng.get_double(0, 6.2832); - 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()( - (a + b*tmp)*cos(u), - (a + b*tmp)*sin(u), - b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); - } - return points; -} - -// a = big radius, b = small radius -template -std::vector generate_points_on_klein_bottle_4D( - double a, double b, bool uniform = false) -{ - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - CGAL::Random rng; - - // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; - - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - { - FT u, v; - if (uniform) - { - int k1 = i / num_lines; - int k2 = i % num_lines; - u = 6.2832 * k1 / num_lines; - v = 6.2832 * k2 / num_lines; - } - else - { - 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), - (a + b*cos(v))*sin(u), - b*sin(v)*cos(u/2), - b*sin(v)*sin(u/2))); - } - return points; -} - int main() { - const int INTRINSIC_DIMENSION = 2; - const int AMBIENT_DIMENSION = 4; + const int INTRINSIC_DIMENSION = 4; + const int AMBIENT_DIMENSION = 5; typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; @@ -158,10 +53,11 @@ int main() CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; - //std::vector points = generate_points_on_plane(); - //std::vector points = generate_points_on_sphere(3.0); - //std::vector points = generate_points_on_klein_bottle_3D(4., 3.); - std::vector points = generate_points_on_klein_bottle_4D(4., 3.); + //std::vector points = generate_points_on_plane(NUM_POINTS); + //std::vector points = generate_points_on_sphere_3(NUM_POINTS, 3.0); + std::vector points = generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //std::vector points = generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + //std::vector points = generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); CGAL::Tangential_complex< Kernel, @@ -179,7 +75,11 @@ int main() output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); + if (INTRINSIC_DIMENSION <= 3) + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + else + tc.number_of_inconsistent_simplices(); + double export_time = t.elapsed(); t.reset(); std::cerr << std::endl diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h new file mode 100644 index 00000000000..6391fe1da6f --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -0,0 +1,152 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Clement Jamin +// +//****************************************************************************** +// File Description : +// +//****************************************************************************** + +#ifndef CGAL_TC_TEST_TEST_UTILITIES_H +#define CGAL_TC_TEST_TEST_UTILITIES_H + +#include +#include +#include + +template +std::vector generate_points_on_plane(std::size_t num_points) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + 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)); + } + return points; +} + +template +std::vector generate_points_on_sphere_3( + std::size_t num_points, double radius) +{ + CGAL::Random_points_on_sphere_3 generator(radius); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + points.push_back(*generator++); + return points; +} + +template +std::vector generate_points_on_sphere_d( + std::size_t num_points, int dim, double radius) +{ + CGAL::Random_points_on_sphere_d generator(dim, radius); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + points.push_back(*generator++); + return points; +} + +// a = big radius, b = small radius +template +std::vector generate_points_on_klein_bottle_3D( + std::size_t num_points, double a, double b, bool uniform = false) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } + else + { + u = rng.get_double(0, 6.2832); + 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()( + (a + b*tmp)*cos(u), + (a + b*tmp)*sin(u), + b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); + } + return points; +} + +// a = big radius, b = small radius +template +std::vector generate_points_on_klein_bottle_4D( + std::size_t num_points, double a, double b, bool uniform = false) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } + else + { + 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)) ); + } + return points; +} + +#endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H From 7f11985e6919136042912ef75f37293ca9f9ff45 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 18:58:48 +0200 Subject: [PATCH 121/487] Comment noise + add generate_points_on_circle_2 --- .../test/Tangential_complex/test_utilities.h | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 6391fe1da6f..c6ad351a120 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -27,6 +27,7 @@ #define CGAL_TC_TEST_TEST_UTILITIES_H #include +#include #include #include @@ -47,6 +48,18 @@ std::vector generate_points_on_plane(std::size_t num_points) return points; } +template +std::vector generate_points_on_circle_2( + std::size_t num_points, double radius) +{ + CGAL::Random_points_on_circle_2 generator(radius); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + points.push_back(*generator++); + return points; +} + template std::vector generate_points_on_sphere_3( std::size_t num_points, double radius) @@ -141,10 +154,10 @@ std::vector generate_points_on_klein_bottle_4D( 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)) ); + (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)*/) ); } return points; } From ff4491a7b3c709b531caad37a9ec4212cad62cde Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 19:00:07 +0200 Subject: [PATCH 122/487] Trick to export complexes with intrinsic dim = 2 --- .../include/CGAL/Tangential_complex.h | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 473aee33c72..5c03866e9c1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -290,7 +290,7 @@ public: #endif os << "OFF \n" - << m_points.size() << " " + << num_vertices << " " << num_simplices << " " << "0 \n" << output.str(); @@ -856,7 +856,11 @@ private: num_vertices = 0; return os; } - + + // If Intrinsic_dimension = 1, we output each point two times + // to be able to export each segment as a flat triangle with 3 different + // indices (otherwise, Meshlab detects degenerated simplices) + const int N = (Intrinsic_dimension == 1 ? 2 : 1); const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors @@ -872,22 +876,26 @@ private: // For each point p for ( ; it_p != it_p_end ; ++it_p) { - int i = 0; - for ( ; i < num_coords ; ++i) - os << CGAL::to_double(coord(*it_p, i)) << " "; - if (i == 2) - os << "0"; + for (int ii = 0 ; ii < N ; ++ii) + { + int i = 0; + for ( ; i < num_coords ; ++i) + os << CGAL::to_double(coord(*it_p, i)) << " "; + if (i == 2) + os << "0"; #ifdef CGAL_TC_EXPORT_NORMALS - for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double(coord(*it_n, i)); + for (i = 0 ; i < num_coords ; ++i) + os << " " << CGAL::to_double(coord(*it_n, i)); +#endif + os << std::endl; + } +#ifdef CGAL_TC_EXPORT_NORMALS ++it_n; #endif - - os << std::endl; } - num_vertices = m_points.size(); + num_vertices = N*m_points.size(); return os; } @@ -897,6 +905,11 @@ private: std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) { + // If Intrinsic_dimension = 1, each point is output two times + // (see export_vertices_to_off) + int factor = (Intrinsic_dimension == 1 ? 2 : 1); + int OFF_simplices_dim = + (Intrinsic_dimension == 1 ? 3 : Intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; Tr_container::const_iterator it_tr = m_triangulations.begin(); @@ -927,12 +940,16 @@ private: { std::set c; std::stringstream sstr_c; + std::size_t data; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) { - std::size_t data = (*it_c)->vertex(i)->data(); - sstr_c << data << " "; + data = (*it_c)->vertex(i)->data(); + sstr_c << data*factor << " "; c.insert(data); } + // See export_vertices_to_off + if (Intrinsic_dimension == 1) + sstr_c << (data*factor + 1) << " "; bool excluded = (excluded_simplices @@ -940,7 +957,7 @@ private: if (!excluded) { - os << Intrinsic_dimension + 1 << " " << sstr_c.str() << " "; + os << OFF_simplices_dim << " " << sstr_c.str() << " "; if (color_inconsistencies && is_simplex_consistent(c)) os << color.str(); else @@ -952,7 +969,7 @@ private: } else if (show_excluded_vertices_in_color) { - os << Intrinsic_dimension + 1 << " " + os << OFF_simplices_dim << " " << sstr_c.str() << " " << "0 0 255"; ++num_simplices; @@ -960,9 +977,17 @@ private: } else { - os << Intrinsic_dimension + 1 << " "; + os << OFF_simplices_dim << " "; + std::size_t data; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - os << (*it_c)->vertex(i)->data() << " "; + { + data = (*it_c)->vertex(i)->data(); + os << data*factor << " "; + } + // See export_vertices_to_off + if (Intrinsic_dimension == 1) + os << (data*factor + 1) << " "; + ++num_simplices; } From db6dbb9aa98f586f3c2f304a90b8556e93356bed Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 19:00:32 +0200 Subject: [PATCH 123/487] Test generate_points_on_circle_2 + code reorganization --- .../test_tangential_complex.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 1123f9a81f6..6dcfc98366b 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -29,14 +29,6 @@ int main() { - const int INTRINSIC_DIMENSION = 4; - const int AMBIENT_DIMENSION = 5; - - typedef CGAL::Epick_d > Kernel; - typedef Kernel::Point_d Point; - - //CGAL::default_random = CGAL::Random(0); // NO RANDOM - #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG tbb::task_scheduler_init init(1); @@ -45,6 +37,12 @@ int main() # endif #endif + const int INTRINSIC_DIMENSION = 1; + const int AMBIENT_DIMENSION = 2; + + typedef CGAL::Epick_d > Kernel; + typedef Kernel::Point_d Point; + int i = 0; bool stop = false; //for ( ; !stop ; ++i) @@ -53,9 +51,10 @@ int main() CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; + std::vector points = generate_points_on_circle_2(NUM_POINTS, 3.); //std::vector points = generate_points_on_plane(NUM_POINTS); //std::vector points = generate_points_on_sphere_3(NUM_POINTS, 3.0); - std::vector points = generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //std::vector points = generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); //std::vector points = generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); //std::vector points = generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); From 491e02b85a1e17ef1137f561de56b13b270fdd80 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 19:35:18 +0200 Subject: [PATCH 124/487] Stop using Kernel_traits + add generate_points_on_moment_curve --- .../test_tangential_complex.cpp | 17 +++--- .../test/Tangential_complex/test_utilities.h | 53 +++++++++++++------ 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 6dcfc98366b..9e8f1cabe14 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -38,7 +37,7 @@ int main() #endif const int INTRINSIC_DIMENSION = 1; - const int AMBIENT_DIMENSION = 2; + const int AMBIENT_DIMENSION = 3; typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; @@ -51,12 +50,14 @@ int main() CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; - std::vector points = generate_points_on_circle_2(NUM_POINTS, 3.); - //std::vector points = generate_points_on_plane(NUM_POINTS); - //std::vector points = generate_points_on_sphere_3(NUM_POINTS, 3.0); - //std::vector points = generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); - //std::vector points = generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - //std::vector points = generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + std::vector points = + //generate_points_on_circle_2(NUM_POINTS, 3.); + generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); + //generate_points_on_plane(NUM_POINTS); + //generate_points_on_sphere_3(NUM_POINTS, 3.0); + //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); CGAL::Tangential_complex< Kernel, diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index c6ad351a120..0c27cf8dea3 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -31,10 +31,10 @@ #include #include -template -std::vector generate_points_on_plane(std::size_t num_points) +template +std::vector generate_points_on_plane(std::size_t num_points) { - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; CGAL::Random rng; std::vector points; @@ -48,8 +48,31 @@ std::vector generate_points_on_plane(std::size_t num_points) return points; } -template -std::vector generate_points_on_circle_2( +template +std::vector generate_points_on_moment_curve( + std::size_t num_points, int dim, + typename Kernel::FT min_x , typename Kernel::FT max_x) +{ + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + CGAL::Random rng; + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT x = rng.get_double(min_x, max_x); + std::vector 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())); + } + return points; +} + +template +std::vector generate_points_on_circle_2( std::size_t num_points, double radius) { CGAL::Random_points_on_circle_2 generator(radius); @@ -60,8 +83,8 @@ std::vector generate_points_on_circle_2( return points; } -template -std::vector generate_points_on_sphere_3( +template +std::vector generate_points_on_sphere_3( std::size_t num_points, double radius) { CGAL::Random_points_on_sphere_3 generator(radius); @@ -72,8 +95,8 @@ std::vector generate_points_on_sphere_3( return points; } -template -std::vector generate_points_on_sphere_d( +template +std::vector generate_points_on_sphere_d( std::size_t num_points, int dim, double radius) { CGAL::Random_points_on_sphere_d generator(dim, radius); @@ -85,11 +108,11 @@ std::vector generate_points_on_sphere_d( } // a = big radius, b = small radius -template -std::vector generate_points_on_klein_bottle_3D( +template +std::vector generate_points_on_klein_bottle_3D( std::size_t num_points, double a, double b, bool uniform = false) { - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; CGAL::Random rng; @@ -124,11 +147,11 @@ std::vector generate_points_on_klein_bottle_3D( } // a = big radius, b = small radius -template -std::vector generate_points_on_klein_bottle_4D( +template +std::vector generate_points_on_klein_bottle_4D( std::size_t num_points, double a, double b, bool uniform = false) { - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; CGAL::Random rng; From f455969e08b2d55ba1f4121fa944c4e5706e5b0c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Oct 2014 15:29:38 +0200 Subject: [PATCH 125/487] Display the number of vertices + bug fix when there is very few points --- Tangential_complex/include/CGAL/Tangential_complex.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5c03866e9c1..6ef57c2b8ca 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -230,6 +230,7 @@ public: std::cerr << std::endl << "================================================" << std::endl << "Inconsistencies:\n" + << " * Number of vertices: " << m_points.size() << std::endl << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << std::endl << " * Number of inconsistent simplices in stars (incl. duplicates): " @@ -920,6 +921,9 @@ private: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); + if (tr.current_dimension() < Intrinsic_dimension) + continue; + // Color for this star std::stringstream color; //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; @@ -999,12 +1003,15 @@ private: std::cerr << std::endl << "================================================" << std::endl << "Export to OFF:\n" + << " * Number of vertices: " << m_points.size() << std::endl << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << std::endl << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl << " * Percentage of inconsistencies: " - << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl + << (num_simplices > 0 ? + 100 * num_inconsistent_simplices / num_simplices : 0) << "%" + << std::endl << "================================================" << std::endl; #endif From d0544766e5cb5bd008585abb1d7a454673626383 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Oct 2014 15:30:40 +0200 Subject: [PATCH 126/487] New constructor to include only a part of the vertices into the tree --- .../include/CGAL/Tangential_complex/Point_cloud.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index a8f53b8c24c..3cbd0d16048 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -262,6 +262,19 @@ public: { } + /// Constructor + Point_cloud_data_structure( + Point_container_ const& points, + std::size_t begin_idx, std::size_t past_the_end_idx) + : m_points(points), + m_tree( + boost::counting_iterator(begin_idx), + boost::counting_iterator(past_the_end_idx), + Tree::Splitter(), + STraits((Point*)&(points[0])) ) + { + } + /*Point_container_ &points() { return m_points; From ec11025811becf6af05c6f341aace6d565158b41 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Oct 2014 15:31:31 +0200 Subject: [PATCH 127/487] Precompiled headers --- .../test/Tangential_complex/CMakeLists.txt | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt index 8d58f3631fe..c1b10d3b85c 100644 --- a/Tangential_complex/test/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -13,6 +13,35 @@ if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) endif() endif() +# Creates a new CMake option, turned ON by default +option(ACTIVATE_MSVC_PRECOMPILED_HEADERS + "Activate precompiled headers in MSVC" + OFF) + +# Macro to add precompiled headers for MSVC +# This function does two things: +# 1. Enable precompiled headers on each file which is listed in "SourcesVar". +# 2. Add the content of "PrecompiledSource" (e.g. "StdAfx.cpp") to "SourcesVar". +MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar) + IF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS) + GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE) + SET(Sources ${${SourcesVar}}) + + SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource} + PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\"") + SET_SOURCE_FILES_PROPERTIES(${Sources} + PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeaders}\" /FI\"${PrecompiledHeader}\"") + # Add precompiled header to SourcesVar + LIST(APPEND ${SourcesVar} ${PrecompiledSource}) + ENDIF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS) +ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER) + +# The compiler might need more memory because of precompiled headers +if(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS AND NOT(MSVC_VERSION LESS 1310)) + set(CGAL_C_FLAGS "${CGAL_C_FLAGS} /Zm1000") + set(CGAL_CXX_FLAGS "${CGAL_CXX_FLAGS} /Zm1000") +endif() + find_package(CGAL QUIET COMPONENTS Core ) if ( CGAL_FOUND ) @@ -34,7 +63,9 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") include_directories (BEFORE "include") - create_single_source_cgal_program( "test_tangential_complex.cpp" ) + set (SOURCE_FILES "test_tangential_complex.cpp") + ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES) + create_single_source_cgal_program( ${SOURCE_FILES} ) else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") From 834a7554f42153a5a46a524154ed1345705ef521 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Oct 2014 15:32:18 +0200 Subject: [PATCH 128/487] Add a function to sparsify a point set and test it --- .../test_tangential_complex.cpp | 17 ++-- .../test/Tangential_complex/test_utilities.h | 79 +++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 9e8f1cabe14..f0ea68f33aa 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 500; + const int NUM_POINTS = 5000; #endif int main() @@ -36,33 +36,38 @@ int main() # endif #endif - const int INTRINSIC_DIMENSION = 1; - const int AMBIENT_DIMENSION = 3; + const int INTRINSIC_DIMENSION = 2; + const int AMBIENT_DIMENSION = 4; typedef CGAL::Epick_d > Kernel; + typedef Kernel::FT FT; typedef Kernel::Point_d Point; int i = 0; bool stop = false; //for ( ; !stop ; ++i) { + Kernel k; Wall_clock_timer t; CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; std::vector points = //generate_points_on_circle_2(NUM_POINTS, 3.); - generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); + //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); //generate_points_on_plane(NUM_POINTS); //generate_points_on_sphere_3(NUM_POINTS, 3.0); //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - //generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + + points = sparsify_point_set(k, points, FT(0.2)*FT(0.2)); CGAL::Tangential_complex< Kernel, INTRINSIC_DIMENSION, - CGAL::Parallel_tag> tc(points.begin(), points.end()); + CGAL::Parallel_tag> tc(points.begin(), points.end(), k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 0c27cf8dea3..43d698e2b80 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -30,6 +30,42 @@ #include #include #include +#include + +template +std::vector +sparsify_point_set( + const Kernel &k, Point_container const& input_pts, + typename Kernel::FT min_squared_dist) +{ + typedef typename Point_container::value_type Point; + typedef typename CGAL::Point_cloud_data_structure Points_ds; + + typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); + + // Create the output container and push the first point into it + std::vector output; + Point_container::const_iterator it_pt = input_pts.begin(); + output.push_back(*it_pt); + ++it_pt; + + // Parse the following points, and add them if they are not too close to + // the other points + std::size_t c = 1; + for ( ; + it_pt != input_pts.end(); + ++it_pt) + { + Points_ds points_ds(output, 0, c); + if (points_ds.query_ANN(*it_pt, 1).begin()->second >= min_squared_dist) + { + output.push_back(*it_pt); + ++c; + } + } + + return output; +} template std::vector generate_points_on_plane(std::size_t num_points) @@ -185,4 +221,47 @@ std::vector generate_points_on_klein_bottle_4D( return points; } + +// a = big radius, b = small radius +template +std::vector +generate_points_on_klein_bottle_variant_5D( + std::size_t num_points, double a, double b, bool uniform = false) +{ + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } + else + { + u = rng.get_double(0, 6.2832); + v = rng.get_double(0, 6.2832); + } + FT x1 = (a + b*cos(v))*cos(u); + FT x2 = (a + b*cos(v))*sin(u); + 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) ); + } + return points; +} + #endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H From 20177a0d75237e9596f70a4a4eaaab2f64566d3c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 17 Oct 2014 14:38:07 +0200 Subject: [PATCH 129/487] Missing typedefs --- Tangential_complex/test/Tangential_complex/test_utilities.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 43d698e2b80..70212f9b3dd 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -111,6 +111,7 @@ template std::vector generate_points_on_circle_2( std::size_t num_points, double radius) { + typedef typename Kernel::Point_d Point; CGAL::Random_points_on_circle_2 generator(radius); std::vector points; points.reserve(NUM_POINTS); @@ -123,6 +124,7 @@ template std::vector generate_points_on_sphere_3( std::size_t num_points, double radius) { + typedef typename Kernel::Point_d Point; CGAL::Random_points_on_sphere_3 generator(radius); std::vector points; points.reserve(NUM_POINTS); @@ -135,6 +137,7 @@ template std::vector generate_points_on_sphere_d( std::size_t num_points, int dim, double radius) { + typedef typename Kernel::Point_d Point; CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector points; points.reserve(NUM_POINTS); From b1f795a6da9923d64bcf70db65412674107e9b65 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 17 Oct 2014 17:34:06 +0200 Subject: [PATCH 130/487] Fisrt try to remove inconsistencies. Not very good. --- .../include/CGAL/Tangential_complex.h | 219 +++++++++++++++--- .../include/CGAL/Tangential_complex/config.h | 1 + .../test_tangential_complex.cpp | 37 ++- 3 files changed, 213 insertions(+), 44 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6ef57c2b8ca..9784b27ce9d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -103,6 +103,7 @@ class Tangential_complex typedef std::vector Tangent_space_basis; typedef std::vector Points; + typedef std::vector Weights; typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; @@ -150,11 +151,19 @@ public: template Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), m_points(first, last), m_points_ds(m_points) {} + : m_k(k), + m_points(first, last), + m_points_ds(m_points) + {} /// Destructor ~Tangential_complex() {} + std::size_t number_of_vertices() + { + return m_points.size(); + } + void compute_tangential_complex() { #ifdef CGAL_TC_PROFILING @@ -166,6 +175,7 @@ public: // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); m_tangent_spaces.resize(m_points.size()); + m_weights.resize(m_points.size(), FT(0)); #ifdef CGAL_TC_EXPORT_NORMALS m_normals.resize(m_points.size()); #endif @@ -192,8 +202,136 @@ public: #endif } + void refresh_tangential_complex() + { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif + +#ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) + { + tbb::parallel_for(tbb::blocked_range(0, m_points.size()), + Compute_tangent_triangulation(*this, true) + ); + } + // Sequential + else +#endif // CGAL_LINKED_WITH_TBB + { + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + compute_tangent_triangulation(i, true); + } + +#ifdef CGAL_TC_PROFILING + std::cerr << "Tangential complex refreshed in " << t.elapsed() + << " seconds." << std::endl; +#endif + } + + void fix_inconsistencies() + { + Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); + Kernel::Construct_weighted_point_d cwp = + m_k.construct_weighted_point_d_object(); + + std::pair stats_before = + number_of_inconsistent_simplices(false); + + bool done = false; + while (!done) + { + std::size_t num_failures = 0; + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for (int pt_idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++pt_idx) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + c.insert(data); + } + + // Inconsistent? + if (!is_simplex_consistent(c)) + { + bool fixed = false; + // Try to find a weight that solves the inconsistency + for (int i = 0 ; i < 50 && !fixed ; ++i) + { + CGAL::Random rng; + m_weights[pt_idx] = + rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + + for (std::size_t j : c) // CJTODO: C++11 + compute_tangent_triangulation(j); + + fixed = is_simplex_consistent(c); + } + if (!fixed) + ++num_failures; + + refresh_tangential_complex(); // CJTODO: heavy computation! + } + } + } + + std::pair stats_after = + number_of_inconsistent_simplices(false); + +#ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "================================================" << std::endl + << "Inconsistencies:\n" + << " * Number of vertices: " << m_points.size() << std::endl + << std::endl + << " * BEFORE fix_inconsistencies:" << std::endl + << " - Total number of simplices in stars (incl. duplicates): " + << stats_before.first << std::endl + << " - Number of inconsistent simplices in stars (incl. duplicates): " + << stats_before.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_before.second / stats_before.first << "%" + << std::endl + << std::endl + << " * AFTER fix_inconsistencies:" << std::endl + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Number of inconsistent simplices in stars (incl. duplicates): " + << stats_after.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_before.first << "%" + << std::endl + << "================================================" << std::endl; +#endif + done = (stats_after.second == 0); + stats_before = stats_after; + } + } + + // Return a pair - std::pair number_of_inconsistent_simplices() + std::pair number_of_inconsistent_simplices( +#ifdef CGAL_TC_VERBOSE + bool verbose = true +#else + bool verbose = false +#endif + ) { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; @@ -213,32 +351,26 @@ public: // For each cell for ( ; it_c != it_c_end ; ++it_c) { - std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - { - std::size_t data = (*it_c)->vertex(i)->data(); - c.insert(data); - } - - if (!is_simplex_consistent(c)) + if (!is_simplex_consistent(*it_c)) ++num_inconsistent_simplices; ++num_simplices; } } -#ifdef CGAL_TC_VERBOSE - std::cerr << std::endl - << "================================================" << std::endl - << "Inconsistencies:\n" - << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices in stars (incl. duplicates): " - << num_simplices << std::endl - << " * Number of inconsistent simplices in stars (incl. duplicates): " - << num_inconsistent_simplices << std::endl - << " * Percentage of inconsistencies: " - << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl - << "================================================" << std::endl; -#endif + if (verbose) + { + std::cerr << std::endl + << "================================================" << std::endl + << "Inconsistencies:\n" + << " * Number of vertices: " << m_points.size() << std::endl + << " * Total number of simplices in stars (incl. duplicates): " + << num_simplices << std::endl + << " * Number of inconsistent simplices in stars (incl. duplicates): " + << num_inconsistent_simplices << std::endl + << " * Percentage of inconsistencies: " + << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl + << "================================================" << std::endl; + } return std::make_pair(num_simplices, num_inconsistent_simplices); } @@ -475,11 +607,14 @@ private: class Compute_tangent_triangulation { Tangential_complex & m_tc; + bool m_tangent_spaces_are_already_computed; public: // Constructor - Compute_tangent_triangulation(Tangential_complex &tc) - : m_tc(tc) + Compute_tangent_triangulation( + Tangential_complex &tc, bool tangent_spaces_are_already_computed = false) + : m_tc(tc), + m_tangent_spaces_are_already_computed(tangent_spaces_are_already_computed) {} // Constructor @@ -491,12 +626,16 @@ private: void operator()( const tbb::blocked_range& r ) const { for( size_t i = r.begin() ; i != r.end() ; ++i) - m_tc.compute_tangent_triangulation(i); + { + m_tc.compute_tangent_triangulation( + i, m_tangent_spaces_are_already_computed); + } } }; #endif // CGAL_LINKED_WITH_TBB - void compute_tangent_triangulation(std::size_t i) + void compute_tangent_triangulation( + std::size_t i, bool tangent_spaces_are_already_computed = false) { //std::cerr << "***********************************************" << std::endl; Triangulation &local_tr = @@ -520,11 +659,14 @@ private: // Estimate the tangent space const Point ¢er_pt = m_points[i]; + if (!tangent_spaces_are_already_computed) + { #ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); + m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt); + m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif + } //*************************************************** // Build a minimal triangulation in the tangent space @@ -534,7 +676,7 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(Intrinsic_dimension, ORIGIN), - 0); + m_weights[i]); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -569,7 +711,7 @@ private: FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); - FT w = -squared_dist_to_tangent_plane; + FT w = -squared_dist_to_tangent_plane + m_weights[neighbor_point_idx]; Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( drop_w(proj_pt), w); @@ -813,6 +955,18 @@ private: m_k.squared_distance_d_object()(p, projected_pt) ); } + + // A simplex here is a local tri's full cell handle + bool is_simplex_consistent(Tr_full_cell_handle fch) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = fch->vertex(i)->data(); + c.insert(data); + } + return is_simplex_consistent(c); + } // A simplex here is a list of point indices bool is_simplex_consistent(std::set const& simplex) @@ -1010,7 +1164,7 @@ private: << num_inconsistent_simplices << std::endl << " * Percentage of inconsistencies: " << (num_simplices > 0 ? - 100 * num_inconsistent_simplices / num_simplices : 0) << "%" + 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" << std::endl << "================================================" << std::endl; #endif @@ -1021,6 +1175,7 @@ private: private: const Kernel m_k; Points m_points; + Weights m_weights; Points_ds m_points_ds; TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index f6e830ef9f8..ce88cf276c4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -32,5 +32,6 @@ //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; +const double INPUT_SPARSITY = 0.5; #endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index f0ea68f33aa..25006c3ebde 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 5000; + const int NUM_POINTS = 100; #endif int main() @@ -37,7 +37,7 @@ int main() #endif const int INTRINSIC_DIMENSION = 2; - const int AMBIENT_DIMENSION = 4; + const int AMBIENT_DIMENSION = 4; typedef CGAL::Epick_d > Kernel; typedef Kernel::FT FT; @@ -62,7 +62,10 @@ int main() generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); - points = sparsify_point_set(k, points, FT(0.2)*FT(0.2)); + points = sparsify_point_set( + k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + std::cerr << "Number of points after sparsification: " + << points.size() << std::endl; CGAL::Tangential_complex< Kernel, @@ -76,24 +79,34 @@ int main() std::set > incorrect_simplices; //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); - std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION - << "_in_R" << AMBIENT_DIMENSION << ".off"; - std::ofstream off_stream(output_filename.str()); - if (INTRINSIC_DIMENSION <= 3) - tc.export_to_off(off_stream, true, &incorrect_simplices, true); - else - tc.number_of_inconsistent_simplices(); + t.reset(); + tc.fix_inconsistencies(); + double fix_time = t.elapsed(); t.reset(); + + double export_time = -1.; + if (INTRINSIC_DIMENSION <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + double export_time = t.elapsed(); t.reset(); + } + /*else + tc.number_of_inconsistent_simplices();*/ - double export_time = t.elapsed(); t.reset(); std::cerr << std::endl << "================================================" << std::endl + << "Number of vertices: " << tc.number_of_vertices() << std::endl << "Computation times (seconds): " << std::endl << " * Tangential complex: " << init_time + computation_time << std::endl << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl + << " * Fix inconsistencies: " << fix_time << std::endl << " * Export to OFF: " << export_time << std::endl << "================================================" << std::endl << std::endl; From 8c5e28cd3d44f2786cef1dc26604fbff32e5a1db Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 21 Oct 2014 17:20:20 +0200 Subject: [PATCH 131/487] Power_center. --- .../include/CGAL/NewKernel_d/Types/Sphere.h | 1 - .../CGAL/NewKernel_d/Types/Weighted_point.h | 80 +++++++++++++++++++ .../include/CGAL/NewKernel_d/functor_tags.h | 3 + NewKernel_d/test/NewKernel_d/Epick_d.cpp | 22 +++++ 4 files changed, 105 insertions(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h index 7ab10f16b99..aac6259cd09 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h @@ -57,7 +57,6 @@ template struct Construct_sphere : Store_kernel { typedef typename LA::Square_matrix Matrix; typedef typename LA::Vector Vec; typedef typename LA::Construct_vector CVec; - typedef typename Get_type::type Point; typename Get_functor::type c(this->kernel()); typename Get_functor >::type cp(this->kernel()); typename Get_functor::type pd(this->kernel()); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 32e8b586b58..4c76c32d579 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -75,6 +75,33 @@ template struct Point_weight { } }; +template struct Power_distance : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_distance) + typedef typename Get_type::type first_argument_type; + typedef first_argument_type second_argument_type; + typedef typename Get_type::type result_type; + + result_type operator()(first_argument_type const&a, second_argument_type const&b)const{ + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor::type sd(this->kernel()); + return sd(pdw(a),pdw(b))-pw(a)-pw(b); + } +}; +template struct Power_distance_to_point : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_distance_to_point) + typedef typename Get_type::type first_argument_type; + typedef typename Get_type::type second_argument_type; + typedef typename Get_type::type result_type; + + result_type operator()(first_argument_type const&a, second_argument_type const&b)const{ + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor::type sd(this->kernel()); + return sd(pdw(a),b)-pw(a); + } +}; + template struct Power_test : private Store_kernel { CGAL_FUNCTOR_INIT_STORE(Power_test) typedef R_ R; @@ -114,6 +141,56 @@ template struct In_flat_power_test : private Store_kernel { } }; +// Construct a point at (weighted) distance 0 from all the input +template struct Power_center : Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_center) + typedef typename Get_type::type WPoint; + typedef WPoint result_type; + typedef typename Get_type::type Point; + typedef typename Get_type::type FT; + template + result_type operator()(Iter f, Iter e)const{ + // 2*(x-y).c == (x^2-wx^2)-(y^2-wy^2) + typedef typename R_::LA LA; + typedef typename LA::Square_matrix Matrix; + typedef typename LA::Vector Vec; + typedef typename LA::Construct_vector CVec; + typename Get_functor::type c(this->kernel()); + typename Get_functor >::type cp(this->kernel()); + typename Get_functor::type pd(this->kernel()); + typename Get_functor::type sdo(this->kernel()); + typename Get_functor::type pdp(this->kernel()); + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor >::type cwp(this->kernel()); + + WPoint const& wp0 = *f; + Point const& p0 = pdw(wp0); + int d = pd(p0); + FT const& n0 = sdo(p0) - pw(wp0); + Matrix m(d,d); + Vec b = typename CVec::Dimension()(d); + // Write the point coordinates in lines. + int i; + for(i=0; ++f!=e; ++i) { + WPoint const& wp=*f; + Point const& p=pdw(wp); + FT const& np = sdo(p) - pw(wp); + for(int j=0;j),(Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(Weighted_point_tag,Point_tag),()); @@ -121,5 +198,8 @@ CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_d CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Power_test_tag,(CartesianDKernelFunctors::Power_test),(Weighted_point_tag),(Power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_test_tag,(CartesianDKernelFunctors::In_flat_power_test),(Weighted_point_tag),(In_flat_power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_distance_tag,(CartesianDKernelFunctors::Power_distance),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_distance_to_point_tag,(CartesianDKernelFunctors::Power_distance_to_point),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_center_tag,(CartesianDKernelFunctors::Power_center),(Weighted_point_tag,Point_tag),(Compute_point_cartesian_coordinate_tag,Construct_ttag,Construct_ttag,Point_dimension_tag,Squared_distance_to_origin_tag,Point_drop_weight_tag,Point_weight_tag,Power_distance_to_point_tag)); } // namespace CGAL #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index afe0720955a..56036b09d0e 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -218,6 +218,8 @@ namespace CGAL { CGAL_DECL_COMPUTE(Hyperplane_translation); CGAL_DECL_COMPUTE(Value_at); CGAL_DECL_COMPUTE(Point_weight); + CGAL_DECL_COMPUTE(Power_distance); + CGAL_DECL_COMPUTE(Power_distance_to_point); #undef CGAL_DECL_COMPUTE #define CGAL_DECL_ITER_OBJ(X,Y,Z,C) struct X##_tag {}; \ @@ -268,6 +270,7 @@ namespace CGAL { CGAL_DECL_CONSTRUCT(Point_to_vector,Vector); CGAL_DECL_CONSTRUCT(Vector_to_point,Point); CGAL_DECL_CONSTRUCT(Point_drop_weight,Point); + CGAL_DECL_CONSTRUCT(Power_center,Weighted_point); #undef CGAL_DECL_CONSTRUCT #if 0 #define CGAL_DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \ diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index c98fad5d9cd..96ca0b4c39e 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -74,6 +74,7 @@ void test2(){ typedef typename K1::Ray_d R; typedef typename K1::Iso_box_d IB; typedef typename K1::Flat_orientation_d FO; + typedef typename K1::Weighted_point_d WP; //typedef K1::Construct_point CP; typedef typename K1::Construct_point_d CP; @@ -122,6 +123,12 @@ void test2(){ typedef typename K1::Difference_of_vectors_d DV; typedef typename K1::Difference_of_points_d DP; typedef typename K1::Translated_point_d TP; + typedef typename CGAL::Get_functor::type PC; + typedef typename CGAL::Get_functor::type PoD; + typedef typename K1::Weighted_point_d WP; + typedef typename K1::Construct_weighted_point_d CWP; + typedef typename K1::Point_drop_weight_d PDW; + typedef typename K1::Point_weight_d PW; CGAL_USE_TYPE(AT); CGAL_USE_TYPE(D); @@ -180,6 +187,11 @@ void test2(){ DV dv Kinit(difference_of_vectors_d_object); DP dp Kinit(difference_of_points_d_object); TP tp Kinit(translated_point_d_object); + PC pc (k); + CWP cwp Kinit(construct_weighted_point_d_object); + PDW pdw Kinit(point_drop_weight_d_object); + PW pw Kinit(point_weight_d_object); + PoD pod (k); CGAL_USE(bc); CGAL_USE(pol); @@ -335,6 +347,16 @@ void test2(){ #endif P x2py1 = tp(x2,y1); assert(x2py1[1]==-2); + WP tw[]={cwp(cp(5,0),1.5),cwp(cp(2,std::sqrt(3)),1),cwp(cp(2,-std::sqrt(3)),1)}; + WP xw=pc(tw+0,tw+3); + assert(abs(pod(xw,tw[0]))<.0001); + assert(abs(pod(xw,tw[1]))<.0001); + assert(abs(pod(xw,tw[2]))<.0001); + assert(pdw(xw)[0]<2.95); + assert(pdw(xw)[0]>2.5); + assert(pw(xw)<2.95); + assert(pw(xw)>2.5); + Sp un1; CGAL_USE(un1); H un2; CGAL_USE(un2); S un3; CGAL_USE(un3); From 01e7dfb323f772fac0b8b81c11fffae60d9db266 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sat, 25 Oct 2014 23:54:18 +0200 Subject: [PATCH 132/487] New app for generating Delaunay triangulations from data files --- .../Triangulation/points_to_DT_to_off.cpp | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Triangulation/applications/Triangulation/points_to_DT_to_off.cpp diff --git a/Triangulation/applications/Triangulation/points_to_DT_to_off.cpp b/Triangulation/applications/Triangulation/points_to_DT_to_off.cpp new file mode 100644 index 00000000000..6c6da039129 --- /dev/null +++ b/Triangulation/applications/Triangulation/points_to_DT_to_off.cpp @@ -0,0 +1,42 @@ +#include +#include +#include + +#include + +typedef CGAL::Epick_d K; +typedef CGAL::Delaunay_triangulation DT; + +void test(int dim) +{ + std::stringstream input_filename; + input_filename << "data/points_" << dim << ".cin"; + std::ifstream in(input_filename.str()); + + DT::Point p; + std::vector points; + + int dim_from_file; + in >> dim_from_file; + while(in >> p) + points.push_back(p); + + // Build the Regular Triangulation + DT dt(dim_from_file); + dt.insert(points.begin(), points.end()); + CGAL_assertion(dt.is_valid(true)); + + // Export + std::stringstream output_filename; + output_filename << "data/dt_dim" << dim << ".off"; + std::ofstream off_stream(output_filename.str()); + CGAL::export_triangulation_to_off(off_stream, dt); +} + +int main() +{ + //test(2); + //test(3); + test(10); + return 0; +} From d78071c7f83ed35e75c3838d3797bb8362d88350 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sat, 25 Oct 2014 23:56:01 +0200 Subject: [PATCH 133/487] CMakeLists.txt file for apps --- .../applications/Triangulation/CMakeLists.txt | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 Triangulation/applications/Triangulation/CMakeLists.txt diff --git a/Triangulation/applications/Triangulation/CMakeLists.txt b/Triangulation/applications/Triangulation/CMakeLists.txt new file mode 100644 index 00000000000..1f49e2c545e --- /dev/null +++ b/Triangulation/applications/Triangulation/CMakeLists.txt @@ -0,0 +1,69 @@ +# Created by the script cgal_create_cmake_script_with_options +# This is the CMake script for compiling a set of CGAL applications. + +project( Triangulation_apps ) + + +cmake_minimum_required(VERSION 2.6.2) +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) + if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) + cmake_policy(VERSION 2.8.4) + else() + cmake_policy(VERSION 2.6) + endif() +endif() + +set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true ) + +if ( COMMAND cmake_policy ) + + cmake_policy( SET CMP0003 NEW ) + +endif() + +# CGAL and its components +find_package( CGAL QUIET COMPONENTS ) + +if ( NOT CGAL_FOUND ) + + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() + +endif() + +# include helper file +include( ${CGAL_USE_FILE} ) + + +# Boost and its components +find_package( Boost REQUIRED ) + +if ( NOT Boost_FOUND ) + + message(STATUS "This project requires the Boost library, and will not be compiled.") + + return() + +endif() + +find_package(Eigen3 3.1.0) +if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) +endif() + +# include for local directory +include_directories( BEFORE include ) + +# include for local package +include_directories( BEFORE ../../include ) + + +# Creating entries for all .cpp/.C files with "main" routine +# ########################################################## + +include( CGAL_CreateSingleSourceCGALProgram ) + +create_single_source_cgal_program( "points_to_RT_to_off.cpp" ) +create_single_source_cgal_program( "points_to_DT_to_off.cpp" ) + + From 7115484e5d3e6c233bad5fd7dd37aef4de1318c9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 4 Nov 2014 14:36:04 +0100 Subject: [PATCH 134/487] Better version of the inconsistencies solver --- .../include/CGAL/Tangential_complex.h | 206 +++++++++++++----- 1 file changed, 148 insertions(+), 58 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 9784b27ce9d..b3c492837e6 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -58,6 +58,7 @@ #ifdef CGAL_LINKED_WITH_TBB # include +# include #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) @@ -119,14 +120,21 @@ class Tangential_complex Tr_and_VH(int dim) : m_tr(new Triangulation(dim)) {} - ~Tr_and_VH() { delete m_tr; } + ~Tr_and_VH() { destroy_triangulation(); } Triangulation & construct_triangulation(int dim) - { + { + delete m_tr; m_tr = new Triangulation(dim); return tr(); } + void destroy_triangulation() + { + delete m_tr; + m_tr = NULL; + } + Triangulation & tr() { return *m_tr; } Triangulation const& tr() const { return *m_tr; } @@ -139,8 +147,13 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; - typedef typename std::vector Tr_container; typedef typename std::vector TS_container; + typedef typename std::vector Tr_container; +#ifdef CGAL_LINKED_WITH_TBB + // CJTODO: test other mutexes + // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm + typedef tbb::queuing_mutex Tr_mutex; +#endif #ifdef CGAL_TC_EXPORT_NORMALS typedef typename std::vector Normals; #endif @@ -174,6 +187,9 @@ public: // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); +#ifdef CGAL_LINKED_WITH_TBB + m_tr_mutexes.resize(m_points.size()); +#endif m_tangent_spaces.resize(m_points.size()); m_weights.resize(m_points.size(), FT(0)); #ifdef CGAL_TC_EXPORT_NORMALS @@ -236,60 +252,39 @@ public: Kernel::Construct_weighted_point_d cwp = m_k.construct_weighted_point_d_object(); +#ifdef CGAL_TC_VERBOSE + std::cerr << "Fixing inconsistencies..." << std::endl; +#endif + std::pair stats_before = number_of_inconsistent_simplices(false); + +#ifdef CGAL_TC_VERBOSE + std::cerr << "Initial number of inconsistencies: " + << stats_before.second << std::endl; +#endif bool done = false; while (!done) { - std::size_t num_failures = 0; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); - // For each triangulation - for (int pt_idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++pt_idx) +// CJTODO: the parallel version is not working for now +/*#ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) { - Triangulation const& tr = it_tr->tr(); - Tr_vertex_handle center_vh = it_tr->center_vertex(); - - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); - // For each cell - for ( ; it_c != it_c_end ; ++it_c) - { - std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - { - std::size_t data = (*it_c)->vertex(i)->data(); - c.insert(data); - } - - // Inconsistent? - if (!is_simplex_consistent(c)) - { - bool fixed = false; - // Try to find a weight that solves the inconsistency - for (int i = 0 ; i < 50 && !fixed ; ++i) - { - CGAL::Random rng; - m_weights[pt_idx] = - rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); - - for (std::size_t j : c) // CJTODO: C++11 - compute_tangent_triangulation(j); - - fixed = is_simplex_consistent(c); - } - if (!fixed) - ++num_failures; - - refresh_tangential_complex(); // CJTODO: heavy computation! - } - } + tbb::parallel_for( + tbb::blocked_range(0, m_triangulations.size()), + Try_to_solve_inconsistencies_in_a_local_triangulation(*this) + ); } - + // Sequential + else +#endif // CGAL_LINKED_WITH_TBB*/ + { + for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) + try_to_solve_inconsistencies_in_a_local_triangulation(i); + } + std::pair stats_after = number_of_inconsistent_simplices(false); @@ -973,7 +968,8 @@ private: { // Check if the simplex is in the stars of all its vertices std::set::const_iterator it_point_idx = simplex.begin(); - // For each point + // For each point p of the simplex, we parse the incidents cells of p + // and we check if "simplex" is among them for ( ; it_point_idx != simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; @@ -1003,6 +999,97 @@ private: return true; } +#ifdef CGAL_LINKED_WITH_TBB + // Functor for try_to_solve_inconsistencies_in_a_local_triangulation function + class Try_to_solve_inconsistencies_in_a_local_triangulation + { + Tangential_complex & m_tc; + + public: + // Constructor + Try_to_solve_inconsistencies_in_a_local_triangulation( + Tangential_complex &tc) + : m_tc(tc) + {} + + // Constructor + Try_to_solve_inconsistencies_in_a_local_triangulation( + const Compute_tangent_triangulation &ctt) + : m_tc(ctt.m_tc) + {} + + // operator() + void operator()( const tbb::blocked_range& r ) const + { + for( size_t i = r.begin() ; i != r.end() ; ++i) + m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i); + } + }; +#endif // CGAL_LINKED_WITH_TBB + + void try_to_solve_inconsistencies_in_a_local_triangulation( + std::size_t tr_index) + { +#ifdef CGAL_LINKED_WITH_TBB + Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); +#endif + + Triangulation const& tr = m_triangulations[tr_index].tr(); + Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = + incident_cells.begin(); + std::vector::const_iterator it_c_end= + incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + c.insert(data); + } + + // Inconsistent? + if (!is_simplex_consistent(c)) + { + CGAL::Random rng; + for (std::size_t j : c) // CJTODO: C++11 + { + m_weights[j] = + rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + } + + for (std::size_t j : c) // CJTODO: C++11 + { +#ifdef CGAL_LINKED_WITH_TBB + if (j == tr_index) + { + compute_tangent_triangulation(j); + } + else + { + Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); + compute_tangent_triangulation(j); + } +#else + compute_tangent_triangulation(j); +#endif + } + + refresh_tangential_complex(); // CJTODO: heavy computation! + + // We will try the other cells next time (incident_cells is not + // valid anymore here) + break; + } + } + } + std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices) { @@ -1173,15 +1260,18 @@ private: } private: - const Kernel m_k; - Points m_points; - Weights m_weights; - Points_ds m_points_ds; - TS_container m_tangent_spaces; - Tr_container m_triangulations; // Contains the triangulations - // and their center vertex + const Kernel m_k; + Points m_points; + Weights m_weights; + Points_ds m_points_ds; + TS_container m_tangent_spaces; + Tr_container m_triangulations; // Contains the triangulations + // and their center vertex +#ifdef CGAL_LINKED_WITH_TBB + std::vector m_tr_mutexes; +#endif #ifdef CGAL_TC_EXPORT_NORMALS - Normals m_normals; + Normals m_normals; #endif }; // /class Tangential_complex From 6981ebe0d4f3c9f557a30c2db9e5ff64243962d0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 18 Nov 2014 10:31:26 +0100 Subject: [PATCH 135/487] Do not test consistency of infinite cells + fix indentation --- .../include/CGAL/Tangential_complex.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b3c492837e6..5195c26623e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -253,17 +253,25 @@ public: m_k.construct_weighted_point_d_object(); #ifdef CGAL_TC_VERBOSE - std::cerr << "Fixing inconsistencies..." << std::endl; + std::cerr << "Fixing inconsistencies..." << std::endl; #endif std::pair stats_before = number_of_inconsistent_simplices(false); #ifdef CGAL_TC_VERBOSE - std::cerr << "Initial number of inconsistencies: " - << stats_before.second << std::endl; + std::cerr << "Initial number of inconsistencies: " + << stats_before.second << std::endl; #endif + if (stats_before.second == 0) + { +#ifdef CGAL_TC_VERBOSE + std::cerr << "Nothing to fix." << std::endl; +#endif + return; + } + bool done = false; while (!done) { @@ -346,6 +354,9 @@ public: // For each cell for ( ; it_c != it_c_end ; ++it_c) { + if (tr.is_infinite(*it_c)) // Don't check infinite cells + continue; + if (!is_simplex_consistent(*it_c)) ++num_inconsistent_simplices; ++num_simplices; From 1b32cc956323190a9356f3b518cc78381c3dfcf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 18 Nov 2014 11:02:18 +0100 Subject: [PATCH 136/487] Fix compilation errors for linux --- .../include/CGAL/Tangential_complex.h | 99 ++++++++++--------- .../CGAL/Tangential_complex/Point_cloud.h | 18 ++-- .../CGAL/Tangential_complex/utilities.h | 16 +-- .../test_tangential_complex.cpp | 2 +- .../test/Tangential_complex/test_utilities.h | 51 +++++----- .../include/CGAL/Delaunay_triangulation.h | 6 +- .../CGAL/IO/Triangulation_off_ostream.h | 4 +- .../include/CGAL/Regular_triangulation.h | 3 +- 8 files changed, 102 insertions(+), 97 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b3c492837e6..d044d3395a2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -96,11 +96,11 @@ class Tangential_complex typedef Tr Triangulation; typedef typename Triangulation::Geom_traits Tr_traits; - typedef typename Triangulation::Point Tr_point; + typedef typename Triangulation::Weighted_point Tr_point; typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; - + typedef std::vector Tangent_space_basis; typedef std::vector Points; @@ -248,8 +248,8 @@ public: void fix_inconsistencies() { - Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); - Kernel::Construct_weighted_point_d cwp = + typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); + typename Kernel::Construct_weighted_point_d cwp = m_k.construct_weighted_point_d_object(); #ifdef CGAL_TC_VERBOSE @@ -330,8 +330,8 @@ public: { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { @@ -341,8 +341,10 @@ public: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); + typename std::vector::const_iterator it_c = + incident_cells.begin(); + typename std::vector::const_iterator it_c_end = + incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { @@ -433,30 +435,26 @@ public: return true; const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); - typedef typename Delaunay_triangulation< - Kernel, - Triangulation_data_structure - < - typename Kernel::Dimension, - Triangulation_vertex - > - > DT; + typedef Delaunay_triangulation + > > DT; typedef typename DT::Vertex_handle DT_VH; typedef typename DT::Finite_full_cell_const_iterator FFC_it; typedef std::set Indexed_simplex; - + //------------------------------------------------------------------------- // Build the ambient Delaunay triangulation // Then save its simplices into "amb_dt_simplices" //------------------------------------------------------------------------- DT ambient_dt(ambient_dim); - std::size_t i = 0; - for (Point const& p : m_points) // CJTODO C++11 + for (std::size_t i=0; idata() = i; - ++i; } std::set amb_dt_simplices; @@ -476,15 +474,15 @@ public: amb_dt_simplices.insert(simplex); } } - + //------------------------------------------------------------------------- // Parse the TC and save its simplices into "stars_simplices" //------------------------------------------------------------------------- std::set stars_simplices; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { @@ -493,9 +491,11 @@ public: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); + + typename std::vector::const_iterator it_c = + incident_cells.begin(); + typename std::vector::const_iterator it_c_end = + incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { @@ -563,8 +563,8 @@ private: struct Tr_vertex_to_global_point { - typedef typename Tr_vertex_handle argument_type; - typedef typename Point result_type; + typedef Tr_vertex_handle argument_type; + typedef Point result_type; Tr_vertex_to_global_point(Points const& points) : m_points(points) {} @@ -580,8 +580,8 @@ private: struct Tr_vertex_to_bare_point { - typedef typename Tr_vertex_handle argument_type; - typedef typename Tr_bare_point result_type; + typedef Tr_vertex_handle argument_type; + typedef Tr_bare_point result_type; Tr_vertex_to_bare_point(Tr_traits const& traits) : m_traits(traits) {} @@ -645,11 +645,11 @@ private: m_k.squared_distance_d_object(); // Triangulation's traits functor & objects - Tr_traits::Squared_distance_d sqdist = + typename Tr_traits::Squared_distance_d sqdist = local_tr_traits.squared_distance_d_object(); - Tr_traits::Point_drop_weight_d drop_w = + typename Tr_traits::Point_drop_weight_d drop_w = local_tr_traits.point_drop_weight_d_object(); - Tr_traits::Center_of_sphere_d center_of_sphere = + typename Tr_traits::Center_of_sphere_d center_of_sphere = local_tr_traits.center_of_sphere_d_object(); // Estimate the tangent space @@ -726,8 +726,10 @@ private: local_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); - for (auto cell : incident_cells) // CJTODO C++11 + for (typename std::vector::iterator cit = + incident_cells.begin(); cit != incident_cells.end(); ++cit) { + Tr_full_cell_handle cell = *cit; if (local_tr.is_infinite(cell)) { star_sphere_squared_radius = boost::none; @@ -979,8 +981,8 @@ private: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end= incident_cells.end(); // For each cell bool found = false; for ( ; !found && it_c != it_c_end ; ++it_c) @@ -1040,9 +1042,9 @@ private: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - std::vector::const_iterator it_c = + typename std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= + typename std::vector::const_iterator it_c_end= incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) @@ -1058,14 +1060,15 @@ private: if (!is_simplex_consistent(c)) { CGAL::Random rng; - for (std::size_t j : c) // CJTODO: C++11 + for (std::set::iterator it=c.begin(); it!=c.end(); ++it) { - m_weights[j] = + m_weights[*it] = rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); } - for (std::size_t j : c) // CJTODO: C++11 - { + for (std::set::iterator it=c.begin(); it!=c.end(); ++it) + { + std::size_t j = *it; #ifdef CGAL_LINKED_WITH_TBB if (j == tr_index) { @@ -1113,8 +1116,8 @@ private: #ifdef CGAL_TC_EXPORT_NORMALS Normals::const_iterator it_n = m_normals.begin(); #endif - Points::const_iterator it_p = m_points.begin(); - Points::const_iterator it_p_end = m_points.end(); + typename Points::const_iterator it_p = m_points.begin(); + typename Points::const_iterator it_p_end = m_points.end(); // For each point p for ( ; it_p != it_p_end ; ++it_p) { @@ -1154,8 +1157,8 @@ private: (Intrinsic_dimension == 1 ? 3 : Intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { @@ -1173,8 +1176,8 @@ private: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end= incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 3cbd0d16048..334fcbdcb20 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -226,7 +226,7 @@ class Point_cloud_data_structure { public: typedef typename Point_container_::value_type Point; - typedef typename K Kernel; + typedef K Kernel; typedef typename Kernel::FT FT; typedef CGAL::Search_traits< @@ -254,14 +254,12 @@ public: /// Constructor Point_cloud_data_structure(Point_container_ const& points) : m_points(points), - m_tree( - boost::counting_iterator(0), - boost::counting_iterator(points.size()), - Tree::Splitter(), - STraits((Point*)&(points[0])) ) - { - } - + m_tree(boost::counting_iterator(0), + boost::counting_iterator(points.size()), + typename Tree::Splitter(), + STraits((Point*)&(points[0])) ) + { } + /// Constructor Point_cloud_data_structure( Point_container_ const& points, @@ -270,7 +268,7 @@ public: m_tree( boost::counting_iterator(begin_idx), boost::counting_iterator(past_the_end_idx), - Tree::Splitter(), + typename Tree::Splitter(), STraits((Point*)&(points[0])) ) { } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index bcf66a6dda8..3797268d6ae 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -40,22 +40,22 @@ namespace Tangential_complex_ { typedef std::vector Basis; const int D = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar - + // Kernel functors - K::Squared_length_d sqlen = kernel.squared_length_d_object(); - K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); - K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); - K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); + typename K::Squared_length_d sqlen = kernel.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); + typename K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); + typename K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); Basis output_basis; - Basis::const_iterator inb_it = input_basis.begin(); - Basis::const_iterator inb_it_end = input_basis.end(); + typename Basis::const_iterator inb_it = input_basis.begin(); + typename Basis::const_iterator inb_it_end = input_basis.end(); for (int i = 0 ; inb_it != inb_it_end ; ++inb_it, ++i) { Vector u = *inb_it; - Basis::iterator outb_it = output_basis.begin(); + typename Basis::iterator outb_it = output_basis.begin(); for (int j = 0 ; j < i ; ++j) { Vector const& ej = *outb_it; diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 25006c3ebde..4c4657975e6 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -90,7 +90,7 @@ int main() std::stringstream output_filename; output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; - std::ofstream off_stream(output_filename.str()); + std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); double export_time = t.elapsed(); t.reset(); } diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 70212f9b3dd..d75d02527cb 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -39,13 +39,14 @@ sparsify_point_set( typename Kernel::FT min_squared_dist) { typedef typename Point_container::value_type Point; - typedef typename CGAL::Point_cloud_data_structure Points_ds; - + typedef typename CGAL::Tangential_complex_::Point_cloud_data_structure Points_ds; + typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); // Create the output container and push the first point into it std::vector output; - Point_container::const_iterator it_pt = input_pts.begin(); + typename Point_container::const_iterator it_pt = input_pts.begin(); output.push_back(*it_pt); ++it_pt; @@ -74,8 +75,8 @@ std::vector generate_points_on_plane(std::size_t num_p typedef typename Kernel::FT FT; CGAL::Random rng; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT x = rng.get_double(0, 5); FT y = rng.get_double(0, 5); @@ -93,8 +94,8 @@ std::vector generate_points_on_moment_curve( typedef typename Kernel::FT FT; CGAL::Random rng; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT x = rng.get_double(min_x, max_x); std::vector coords; @@ -114,8 +115,8 @@ std::vector generate_points_on_circle_2( typedef typename Kernel::Point_d Point; CGAL::Random_points_on_circle_2 generator(radius); std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -127,8 +128,8 @@ std::vector generate_points_on_sphere_3( typedef typename Kernel::Point_d Point; CGAL::Random_points_on_sphere_3 generator(radius); std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -140,8 +141,8 @@ std::vector generate_points_on_sphere_d( typedef typename Kernel::Point_d Point; CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -156,12 +157,12 @@ std::vector generate_points_on_klein_bottle_3D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; + int num_lines = (int)sqrt(num_points); + int num_cols = num_points/num_lines + 1; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) @@ -195,12 +196,12 @@ std::vector generate_points_on_klein_bottle_4D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; + int num_lines = (int)sqrt(num_points); + int num_cols = num_points/num_lines + 1; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) @@ -236,12 +237,12 @@ generate_points_on_klein_bottle_variant_5D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; + int num_lines = (int)sqrt(num_points); + int num_cols = num_points/num_lines + 1; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index dfc5ff43210..e30d419b46b 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -75,6 +75,8 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Full_cell_iterator Full_cell_iterator; typedef typename Base::Full_cell_const_handle Full_cell_const_handle; typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename Base::Finite_full_cell_const_iterator + Finite_full_cell_const_iterator; typedef typename Base::size_type size_type; typedef typename Base::difference_type difference_type; @@ -861,8 +863,8 @@ Delaunay_triangulation int dim = current_dimension(); if (dim == maximal_dimension()) { - for (Finite_full_cell_const_iterator cit = finite_full_cells_begin() ; - cit != finite_full_cells_end() ; ++cit ) + for (Finite_full_cell_const_iterator cit = this->finite_full_cells_begin() ; + cit != this->finite_full_cells_end() ; ++cit ) { Full_cell_const_handle ch = cit.base(); for(int i = 0; i < dim+1 ; ++i ) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 590c2a6b0e6..44506b807fa 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -124,8 +124,8 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) std::vector coords; while (line_sstr >> temp) coords.push_back(temp); - - std::vector::iterator last = coords.end() - 1; + + typename std::vector::iterator last = coords.end() - 1; P p = P(coords.begin(), last); wp = WP(p, *last); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index b5174b0f698..0d6dc509f9b 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -68,8 +68,9 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Full_cell Full_cell; typedef typename Base::Facet Facet; typedef typename Base::Face Face; - + typedef Maximal_dimension_ Maximal_dimension; + typedef typename Base::Point Point; typedef typename RTTraits::Bare_point Bare_point; typedef typename RTTraits::Weighted_point Weighted_point; From 3f5bb0cdd54247ed804ad11c004712eb4a69d1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 18 Nov 2014 11:33:31 +0100 Subject: [PATCH 137/487] Fix trailing whitespace --- .../CGAL/NewKernel_d/Cartesian_filter_K.h | 10 +- .../include/CGAL/Tangential_complex.h | 186 +++++++++--------- .../CGAL/Tangential_complex/Point_cloud.h | 66 +++---- .../test_tangential_complex.cpp | 12 +- .../test/Tangential_complex/test_utilities.h | 10 +- .../include/CGAL/Delaunay_triangulation.h | 36 ++-- .../CGAL/IO/Triangulation_off_ostream.h | 18 +- .../include/CGAL/Regular_triangulation.h | 106 +++++----- 8 files changed, 222 insertions(+), 222 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 403a0e4d68c..179e97bf016 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -30,7 +30,7 @@ namespace CGAL { template < typename Base_, typename AK_, typename EK_ > struct Cartesian_filter_K : public Base_, - private Store_kernel, private Store_kernel2 + private Store_kernel, private Store_kernel2 { CGAL_CONSTEXPR Cartesian_filter_K(){} CGAL_CONSTEXPR Cartesian_filter_K(int d):Base_(d){} @@ -61,11 +61,11 @@ struct Cartesian_filter_K : public Base_, template struct Type : Get_type {}; template::type> struct Functor : - Inherit_functor {}; + Inherit_functor {}; template struct Functor { - typedef typename Get_functor::type AP; - typedef typename Get_functor::type EP; - typedef Filtered_predicate2 type; + typedef typename Get_functor::type AP; + typedef typename Get_functor::type EP; + typedef Filtered_predicate2 type; }; // TODO: // template struct Functor : diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d044d3395a2..a505cb47d2a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -66,10 +66,10 @@ namespace CGAL { using namespace Tangential_complex_; - + /// The class Tangential_complex represents a tangential complex template < - typename Kernel, + typename Kernel, int Intrinsic_dimension, typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Regular_triangulation @@ -119,7 +119,7 @@ class Tangential_complex : m_tr(NULL) {} Tr_and_VH(int dim) : m_tr(new Triangulation(dim)) {} - + ~Tr_and_VH() { destroy_triangulation(); } Triangulation & construct_triangulation(int dim) @@ -137,7 +137,7 @@ class Tangential_complex Triangulation & tr() { return *m_tr; } Triangulation const& tr() const { return *m_tr; } - + Tr_vertex_handle const& center_vertex() const { return m_center_vertex; } Tr_vertex_handle & center_vertex() { return m_center_vertex; } @@ -150,23 +150,23 @@ class Tangential_complex typedef typename std::vector TS_container; typedef typename std::vector Tr_container; #ifdef CGAL_LINKED_WITH_TBB - // CJTODO: test other mutexes + // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - typedef tbb::queuing_mutex Tr_mutex; + typedef tbb::queuing_mutex Tr_mutex; #endif #ifdef CGAL_TC_EXPORT_NORMALS typedef typename std::vector Normals; #endif public: - + /// Constructor for a range of points template - Tangential_complex(InputIterator first, InputIterator last, + Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), + : m_k(k), m_points(first, last), - m_points_ds(m_points) + m_points_ds(m_points) {} /// Destructor @@ -195,7 +195,7 @@ public: #ifdef CGAL_TC_EXPORT_NORMALS m_normals.resize(m_points.size()); #endif - + #ifdef CGAL_LINKED_WITH_TBB // Parallel if (boost::is_convertible::value) @@ -211,19 +211,19 @@ public: for (std::size_t i = 0 ; i < m_points.size() ; ++i) compute_tangent_triangulation(i); } - + #ifdef CGAL_TC_PROFILING - std::cerr << "Tangential complex computed in " << t.elapsed() + std::cerr << "Tangential complex computed in " << t.elapsed() << " seconds." << std::endl; #endif } - + void refresh_tangential_complex() { #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif - + #ifdef CGAL_LINKED_WITH_TBB // Parallel if (boost::is_convertible::value) @@ -239,33 +239,33 @@ public: for (std::size_t i = 0 ; i < m_points.size() ; ++i) compute_tangent_triangulation(i, true); } - + #ifdef CGAL_TC_PROFILING - std::cerr << "Tangential complex refreshed in " << t.elapsed() + std::cerr << "Tangential complex refreshed in " << t.elapsed() << " seconds." << std::endl; #endif } - + void fix_inconsistencies() { typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); typename Kernel::Construct_weighted_point_d cwp = m_k.construct_weighted_point_d_object(); - + #ifdef CGAL_TC_VERBOSE std::cerr << "Fixing inconsistencies..." << std::endl; #endif std::pair stats_before = number_of_inconsistent_simplices(false); - + #ifdef CGAL_TC_VERBOSE - std::cerr << "Initial number of inconsistencies: " + std::cerr << "Initial number of inconsistencies: " << stats_before.second << std::endl; #endif bool done = false; - while (!done) + while (!done) { // CJTODO: the parallel version is not working for now /*#ifdef CGAL_LINKED_WITH_TBB @@ -295,21 +295,21 @@ public: << " * Number of vertices: " << m_points.size() << std::endl << std::endl << " * BEFORE fix_inconsistencies:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " + << " - Total number of simplices in stars (incl. duplicates): " << stats_before.first << std::endl - << " - Number of inconsistent simplices in stars (incl. duplicates): " + << " - Number of inconsistent simplices in stars (incl. duplicates): " << stats_before.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_before.second / stats_before.first << "%" + << " - Percentage of inconsistencies: " + << 100. * stats_before.second / stats_before.first << "%" << std::endl << std::endl << " * AFTER fix_inconsistencies:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " + << " - Total number of simplices in stars (incl. duplicates): " << stats_after.first << std::endl - << " - Number of inconsistent simplices in stars (incl. duplicates): " + << " - Number of inconsistent simplices in stars (incl. duplicates): " << stats_after.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_before.first << "%" + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_before.first << "%" << std::endl << "================================================" << std::endl; #endif @@ -317,7 +317,7 @@ public: stats_before = stats_after; } } - + // Return a pair std::pair number_of_inconsistent_simplices( @@ -360,20 +360,20 @@ public: << "================================================" << std::endl << "Inconsistencies:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices in stars (incl. duplicates): " + << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << std::endl - << " * Number of inconsistent simplices in stars (incl. duplicates): " + << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl - << " * Percentage of inconsistencies: " + << " * Percentage of inconsistencies: " << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl << "================================================" << std::endl; } return std::make_pair(num_simplices, num_inconsistent_simplices); } - + std::ostream &export_to_off( - std::ostream & os, + std::ostream & os, bool color_inconsistencies = false, std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) @@ -386,14 +386,14 @@ public: { std::cerr << "Error: export_to_off => ambient dimension should be >= 2." << std::endl; - os << "Error: export_to_off => ambient dimension should be >= 2." + os << "Error: export_to_off => ambient dimension should be >= 2." << std::endl; return os; } if (ambient_dim > 3) { std::cerr << "Warning: export_to_off => ambient dimension should be " - "<= 3. Only the first 3 coordinates will be exported." + "<= 3. Only the first 3 coordinates will be exported." << std::endl; } @@ -412,22 +412,22 @@ public: std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); export_simplices_to_off( - output, num_simplices, color_inconsistencies, + output, num_simplices, color_inconsistencies, excluded_simplices, show_excluded_vertices_in_color); - + #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; #endif os << "OFF \n" - << num_vertices << " " + << num_vertices << " " << num_simplices << " " << "0 \n" << output.str(); return os; } - + bool check_if_all_simplices_are_in_the_ambient_delaunay( std::set > * incorrect_simplices = NULL) { @@ -456,7 +456,7 @@ public: DT_VH vh = ambient_dt.insert(p); vh->data() = i; } - + std::set amb_dt_simplices; for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; @@ -511,7 +511,7 @@ public: stars_simplices.insert(simplex); } } - + //------------------------------------------------------------------------- // Check if simplices of "stars_simplices" are all in "amb_dt_simplices" //------------------------------------------------------------------------- @@ -521,19 +521,19 @@ public: incorrect_simplices = &diff; set_difference(stars_simplices.begin(), stars_simplices.end(), amb_dt_simplices.begin(), amb_dt_simplices.end(), - std::inserter(*incorrect_simplices, + std::inserter(*incorrect_simplices, incorrect_simplices->begin()) ); if (!incorrect_simplices->empty()) { - std::cerr + std::cerr << "ERROR check_if_all_simplices_are_in_the_ambient_delaunay:" << std::endl - << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << " Number of simplices in ambient DT: " << amb_dt_simplices.size() << std::endl - << " Number of unique simplices in TC stars: " << stars_simplices.size() + << " Number of unique simplices in TC stars: " << stars_simplices.size() << std::endl - << " Number of wrong simplices: " << incorrect_simplices->size() + << " Number of wrong simplices: " << incorrect_simplices->size() << std::endl; return false; } @@ -551,7 +551,7 @@ private: bool operator()(Point const& p1, Point const& p2) { - typename Kernel::Squared_distance_d sqdist = + typename Kernel::Squared_distance_d sqdist = m_k.squared_distance_d_object(); return sqdist(p1, m_ref) < sqdist(p2, m_ref); } @@ -608,7 +608,7 @@ private: // Constructor Compute_tangent_triangulation( Tangential_complex &tc, bool tangent_spaces_are_already_computed = false) - : m_tc(tc), + : m_tc(tc), m_tangent_spaces_are_already_computed(tangent_spaces_are_already_computed) {} @@ -641,7 +641,7 @@ private: // Kernel functor & objects typename Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - typename Kernel::Squared_distance_d k_sqdist = + typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); // Triangulation's traits functor & objects @@ -662,7 +662,7 @@ private: m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif } - + //*************************************************** // Build a minimal triangulation in the tangent space // (we only need the star of p) @@ -678,16 +678,16 @@ private: //const int NUM_NEIGHBORS = 150; //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); - + // While building the local triangulation, we keep the radius - // of the sphere "star sphere" centered at "center_vertex" + // of the sphere "star sphere" centered at "center_vertex" // and which contains all the // circumspheres of the star of "center_vertex" boost::optional star_sphere_squared_radius; // Insert points until we find a point which is outside "star shere" - for (INS_iterator nn_it = ins_range.begin() ; - nn_it != ins_range.end() ; + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; ++nn_it) { std::size_t neighbor_point_idx = nn_it->first; @@ -704,13 +704,13 @@ private: Tr_point proj_pt = project_point_and_compute_weight( neighbor_pt, center_pt, m_tangent_spaces[i], local_tr_traits); - FT squared_dist_to_tangent_plane = + FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); FT w = -squared_dist_to_tangent_plane + m_weights[neighbor_point_idx]; Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( drop_w(proj_pt), w); - + Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) @@ -724,7 +724,7 @@ private: // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; local_tr.incident_full_cells( - center_vertex, + center_vertex, std::back_inserter(incident_cells)); for (typename std::vector::iterator cit = incident_cells.begin(); cit != incident_cells.end(); ++cit) @@ -739,7 +739,7 @@ private: { //********************************* // We don't compute the circumsphere of the simplex in the - // local tangent plane since it would involve to take the + // local tangent plane since it would involve to take the // weights of the points into account later // (which is a problem since the ANN is performed on the // points in the ambient dimension) @@ -750,7 +750,7 @@ private: tsb.reserve(Intrinsic_dimension); Point const& orig = m_points[cell->vertex(0)->data()]; for (int ii = 1 ; ii <= Intrinsic_dimension ; ++ii) - { + { tsb.push_back(k_diff_pts( m_points[cell->vertex(ii)->data()], orig)); } @@ -764,12 +764,12 @@ private: proj_pts.push_back(project_point( m_points[cell->vertex(ii)->data()], orig, tsb)); } - + Tr_bare_point c = center_of_sphere( proj_pts.begin(), proj_pts.end()); FT sq_circumdiam = 4.*sqdist(c, proj_pts[0]); - if (!star_sphere_squared_radius + if (!star_sphere_squared_radius || sq_circumdiam > *star_sphere_squared_radius) star_sphere_squared_radius = sq_circumdiam; } @@ -800,7 +800,7 @@ private: // Kernel functors typename Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = + typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); @@ -815,13 +815,13 @@ private: p, NUM_POINTS_FOR_PCA, false); //******************************* PCA ************************************* - + const int amb_dim = m_k.point_dimension_d_object()(p); // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); KNS_iterator nn_it = kns_range.begin(); - for (int j = 0 ; - j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + for (int j = 0 ; + j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { for (int i = 0 ; i < amb_dim ; ++i) @@ -837,14 +837,14 @@ private: for (int i = amb_dim - 1 ; i >= amb_dim - Intrinsic_dimension ; --i) { ts.push_back(constr_vec( - amb_dim, - eig.eigenvectors().col(i).data(), + amb_dim, + eig.eigenvectors().col(i).data(), eig.eigenvectors().col(i).data() + amb_dim)); } #ifdef CGAL_TC_EXPORT_NORMALS *p_normal = constr_vec( - amb_dim, - eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data(), + amb_dim, + eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data(), eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data() + amb_dim); #endif @@ -862,7 +862,7 @@ private: Vector t2(p[1] * t1[2] - p[2] * t1[1], p[2] * t1[0] - p[0] * t1[2], p[0] * t1[1] - p[1] * t1[0]); - + // Normalize t1 and t2 typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); @@ -887,13 +887,13 @@ private: //return compute_gram_schmidt_basis(ts, m_k); */ } - + // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p - Tr_bare_point project_point(const Point &p, const Point &origin, + Tr_bare_point project_point(const Point &p, const Point &origin, const Tangent_space_basis &ts) const { - typename Kernel::Scalar_product_d inner_pdct = + typename Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); @@ -925,7 +925,7 @@ private: m_k.difference_of_points_d_object(); typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); - + Vector v = diff_points(p, origin); std::vector coords; @@ -952,7 +952,7 @@ private: m_k.squared_distance_d_object()(p, projected_pt) ); } - + // A simplex here is a local tri's full cell handle bool is_simplex_consistent(Tr_full_cell_handle fch) { @@ -997,7 +997,7 @@ private: if (!found) return false; } - + return true; } @@ -1101,7 +1101,7 @@ private: num_vertices = 0; return os; } - + // If Intrinsic_dimension = 1, we output each point two times // to be able to export each segment as a flat triangle with 3 different // indices (otherwise, Meshlab detects degenerated simplices) @@ -1109,7 +1109,7 @@ private: const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors - typename Kernel::Compute_coordinate_d coord = + typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); int num_coords = min(ambient_dim, 3); @@ -1128,7 +1128,7 @@ private: os << CGAL::to_double(coord(*it_p, i)) << " "; if (i == 2) os << "0"; - + #ifdef CGAL_TC_EXPORT_NORMALS for (i = 0 ; i < num_coords ; ++i) os << " " << CGAL::to_double(coord(*it_n, i)); @@ -1145,7 +1145,7 @@ private: } std::ostream &export_simplices_to_off( - std::ostream & os, std::size_t &num_simplices, + std::ostream & os, std::size_t &num_simplices, bool color_inconsistencies = false, std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) @@ -1153,7 +1153,7 @@ private: // If Intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) int factor = (Intrinsic_dimension == 1 ? 2 : 1); - int OFF_simplices_dim = + int OFF_simplices_dim = (Intrinsic_dimension == 1 ? 3 : Intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; @@ -1199,10 +1199,10 @@ private: if (Intrinsic_dimension == 1) sstr_c << (data*factor + 1) << " "; - bool excluded = + bool excluded = (excluded_simplices && excluded_simplices->find(c) != excluded_simplices->end()); - + if (!excluded) { os << OFF_simplices_dim << " " << sstr_c.str() << " "; @@ -1217,7 +1217,7 @@ private: } else if (show_excluded_vertices_in_color) { - os << OFF_simplices_dim << " " + os << OFF_simplices_dim << " " << sstr_c.str() << " " << "0 0 255"; ++num_simplices; @@ -1248,13 +1248,13 @@ private: << "================================================" << std::endl << "Export to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices in stars (incl. duplicates): " + << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << std::endl - << " * Number of inconsistent simplices in stars (incl. duplicates): " + << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl - << " * Percentage of inconsistencies: " - << (num_simplices > 0 ? - 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" + << " * Percentage of inconsistencies: " + << (num_simplices > 0 ? + 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" << std::endl << "================================================" << std::endl; #endif @@ -1268,7 +1268,7 @@ private: Weights m_weights; Points_ds m_points_ds; TS_container m_tangent_spaces; - Tr_container m_triangulations; // Contains the triangulations + Tr_container m_triangulations; // Contains the triangulations // and their center vertex #ifdef CGAL_LINKED_WITH_TBB std::vector m_tr_mutexes; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 334fcbdcb20..5b82f49099f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -46,27 +46,27 @@ public: typedef typename Kernel::FT FT; /// The constructor that sets the data set source - Point_cloud_adaptator(Point_container_ &points, Kernel const& k) + Point_cloud_adaptator(Point_container_ &points, Kernel const& k) : m_points(points), m_k(k) {} /// CRTP helper method - inline Point_container_ const& points() const - { + inline Point_container_ const& points() const + { return m_points; - } - inline Point_container_& points() + } + inline Point_container_& points() { return m_points; } // Must return the number of data points - inline size_t kdtree_get_point_count() const + inline size_t kdtree_get_point_count() const { return m_points.size(); } - // Returns the distance between the vector "p1[0:size-1]" + // Returns the distance between the vector "p1[0:size-1]" // and the data point with index "idx_p2" stored in the class: inline FT kdtree_distance( const FT *p1, const size_t idx_p2, size_t size) const @@ -76,18 +76,18 @@ public: } // Returns the dim'th component of the idx'th point in the class: - // Since this is inlined and the "dim" argument is typically an + // Since this is inlined and the "dim" argument is typically an // immediate value, the "if/else's" are actually solved at compile time. inline FT kdtree_get_pt(const size_t idx, int dim) const { return m_k.compute_coordinate_d_object()(points()[idx], dim); } - // Optional bounding-box computation: return false to default to a standard + // Optional bounding-box computation: return false to default to a standard // bbox computation loop. - // Return true if the BBOX was already computed by the class and returned + // Return true if the BBOX was already computed by the class and returned // in "bb" so it can be avoided to redo it again. - // Look at bb.size() to find out the expected dimensionality + // Look at bb.size() to find out the expected dimensionality // (e.g. 2 or 3 for point clouds) template bool kdtree_get_bbox(Bbox &bb) const @@ -100,7 +100,7 @@ public: return m_k; } -protected: +protected: Point_container_& m_points; //!< A ref to the data set origin Kernel const& m_k; //!< A const ref to the kernel @@ -119,13 +119,13 @@ public: /// Constructor Point_cloud_data_structure(Point_container_ &points, Kernel const& k) : m_adaptor(points, k), - m_kd_tree(AMB_DIM, - m_adaptor, + m_kd_tree(AMB_DIM, + m_adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) { m_kd_tree.buildIndex(); } - + /*Point_container_ &points() { return m_adaptor.points(); @@ -150,19 +150,19 @@ public: nanoflann::KNNResultSet result_set(k); result_set.init(neighbor_indices, squared_distance); m_kd_tree.findNeighbors(result_set, - &sp_vec[0], + &sp_vec[0], nanoflann::SearchParams()); /*std::cout << "knnSearch(nn="<< num_results <<"): \n"; for (int i = 0 ; i < num_results ; ++i) { std::cout << " * neighbor_indices = " << neighbor_indices [i] - << " (out_dist_sqr = " << squared_distance[i] << ")" + << " (out_dist_sqr = " << squared_distance[i] << ")" << std::endl; }*/ } - - void query_ball(const Point &sp, + + void query_ball(const Point &sp, const FT radius, std::vector > &neighbors, bool sort_output = true) @@ -182,7 +182,7 @@ public: for (const auto idx_and_dist : neighbors) { std::cout << " * neighbor_indices = " << idx_and_dist.first - << " (out_dist_sqr = " << idx_and_dist.second << ")" + << " (out_dist_sqr = " << idx_and_dist.second << ")" << std::endl; }*/ } @@ -244,7 +244,7 @@ public: typedef K_neighbor_search KNS_range; typedef CGAL::Orthogonal_incremental_neighbor_search< - STraits, Distance, CGAL::Sliding_midpoint, Tree> + STraits, Distance, CGAL::Sliding_midpoint, Tree> Incremental_neighbor_search; typedef typename Incremental_neighbor_search::iterator INS_iterator; typedef Incremental_neighbor_search INS_range; @@ -262,7 +262,7 @@ public: /// Constructor Point_cloud_data_structure( - Point_container_ const& points, + Point_container_ const& points, std::size_t begin_idx, std::size_t past_the_end_idx) : m_points(points), m_tree( @@ -272,7 +272,7 @@ public: STraits((Point*)&(points[0])) ) { } - + /*Point_container_ &points() { return m_points; @@ -283,7 +283,7 @@ public: return m_points; }*/ - KNS_range query_ANN(const + KNS_range query_ANN(const Point &sp, unsigned int k, bool sorted = true) const @@ -292,18 +292,18 @@ public: // Note that we need to pass the Distance explicitly since it needs to // know the property map K_neighbor_search search( - m_tree, - sp, - k, - FT(0), + m_tree, + sp, + k, + FT(0), true, Distance_adapter >( (Point*)&(m_points[0])), sorted); - + return search; } - + INS_range query_incremental_ANN(const Point &sp) const { // Initialize the search structure, and search all N points @@ -312,11 +312,11 @@ public: Incremental_neighbor_search search( m_tree, sp, - FT(0), + FT(0), true, Distance_adapter >( (Point*)&(m_points[0])) ); - + return search; } @@ -330,4 +330,4 @@ protected: #endif // CGAL_TC_USE_NANOFLANN -#endif // POINT_CLOUD_H \ No newline at end of file +#endif // POINT_CLOUD_H diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 4c4657975e6..90f424c7a84 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -51,8 +51,8 @@ int main() Wall_clock_timer t; CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; - - std::vector points = + + std::vector points = //generate_points_on_circle_2(NUM_POINTS, 3.); //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); //generate_points_on_plane(NUM_POINTS); @@ -64,12 +64,12 @@ int main() points = sparsify_point_set( k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); - std::cerr << "Number of points after sparsification: " + std::cerr << "Number of points after sparsification: " << points.size() << std::endl; CGAL::Tangential_complex< - Kernel, - INTRINSIC_DIMENSION, + Kernel, + INTRINSIC_DIMENSION, CGAL::Parallel_tag> tc(points.begin(), points.end(), k); double init_time = t.elapsed(); t.reset(); @@ -113,4 +113,4 @@ int main() } return 0; -} \ No newline at end of file +} diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index d75d02527cb..c8296211c8d 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -35,7 +35,7 @@ template std::vector sparsify_point_set( - const Kernel &k, Point_container const& input_pts, + const Kernel &k, Point_container const& input_pts, typename Kernel::FT min_squared_dist) { typedef typename Point_container::value_type Point; @@ -173,13 +173,13 @@ std::vector generate_points_on_klein_bottle_3D( v = 6.2832 * k2 / num_lines; } else - { + { u = rng.get_double(0, 6.2832); 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()( - (a + b*tmp)*cos(u), + (a + b*tmp)*cos(u), (a + b*tmp)*sin(u), b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); } @@ -212,7 +212,7 @@ std::vector generate_points_on_klein_bottle_4D( v = 6.2832 * k2 / num_lines; } else - { + { u = rng.get_double(0, 6.2832); v = rng.get_double(0, 6.2832); } @@ -253,7 +253,7 @@ generate_points_on_klein_bottle_variant_5D( v = 6.2832 * k2 / num_lines; } else - { + { u = rng.get_double(0, 6.2832); v = rng.get_double(0, 6.2832); } diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index e30d419b46b..790dc8ef789 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -121,7 +121,7 @@ public: using Base::vertices_begin; using Base::vertices_end; // using Base:: - + private: //*** Side_of_oriented_subsphere_d *** typedef typename Base::Flat_orientation_d Flat_orientation_d; @@ -149,7 +149,7 @@ private: } }; public: - + // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS Delaunay_triangulation(int dim, const Geom_traits &k = Geom_traits()) @@ -158,12 +158,12 @@ public: } // With this constructor, - // the user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension // (= preset_flat_orientation_.first) // It it used by the dark triangulations created by DT::remove Delaunay_triangulation( - int dim, + int dim, const std::pair &preset_flat_orientation, const Geom_traits &k = Geom_traits()) : Base(dim, preset_flat_orientation, k) @@ -178,8 +178,8 @@ public: Side_of_oriented_subsphere_d side_of_oriented_subsphere_predicate() const { return Side_of_oriented_subsphere_d ( - flat_orientation_, - geom_traits().construct_flat_orientation_d_object(), + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), geom_traits().in_flat_side_of_oriented_sphere_d_object() ); } @@ -291,7 +291,7 @@ public: Orientation o = ori_( boost::make_transform_iterator(s->vertices_begin(), spivi), - boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, spivi)); if( POSITIVE == o ) @@ -320,9 +320,9 @@ public: return pred_(dc_.full_cell(f)->neighbor(dc_.index_of_covertex(f))); } }; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY - + bool is_valid(bool verbose = false, int level = 0) const; private: @@ -339,7 +339,7 @@ private: Conflict_traversal_pred_in_fullspace; }; -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // FUNCTIONS THAT ARE MEMBER METHODS: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS @@ -530,7 +530,7 @@ Delaunay_triangulation typedef typename Base::template Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); - + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); // Make the dark simplices in the conflict zone searchable conflict_zone.make_searchable(); @@ -628,7 +628,7 @@ Delaunay_triangulation int li = light_s->index(dark_s->vertex(di)->data()); Rotor light_r(light_s, li, light_i); typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); - + while( simps.contains(full_cell(light_r)->neighbor(index_of_covertex(light_r))) ) light_r = rotate_rotor(light_r); @@ -856,7 +856,7 @@ template< typename DCTraits, typename TDS > bool Delaunay_triangulation ::is_valid(bool verbose, int level) const -{ +{ if (!Base::is_valid(verbose, level)) return false; @@ -867,16 +867,16 @@ Delaunay_triangulation cit != this->finite_full_cells_end() ; ++cit ) { Full_cell_const_handle ch = cit.base(); - for(int i = 0; i < dim+1 ; ++i ) + for(int i = 0; i < dim+1 ; ++i ) { // If the i-th neighbor is not an infinite cell - Vertex_handle opposite_vh = + Vertex_handle opposite_vh = ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); if (!is_infinite(opposite_vh)) { - Side_of_oriented_sphere_d side = + Side_of_oriented_sphere_d side = geom_traits().side_of_oriented_sphere_d_object(); - if (side(Point_const_iterator(ch->vertices_begin()), + if (side(Point_const_iterator(ch->vertices_begin()), Point_const_iterator(ch->vertices_end()), opposite_vh->point()) == ON_BOUNDED_SIDE) { diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 44506b807fa..1ca28265e21 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -53,7 +53,7 @@ input_point(std::istream & is, const Traits &traits, P & p) { typedef typename Traits::FT FT; std::vector coords; - + std::string line; for(;;) { @@ -84,7 +84,7 @@ operator>>(std::istream &is, typename Wrap::Point_d & p) typedef typename Wrap::Point_d P; typedef typename K::FT FT; std::vector coords; - + std::string line; for(;;) { @@ -134,7 +134,7 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) template < class GT, class TDS > std::ostream & -export_triangulation_to_off(std::ostream & os, +export_triangulation_to_off(std::ostream & os, const Triangulation & tr, bool in_3D_export_surface_only = false) { @@ -147,7 +147,7 @@ export_triangulation_to_off(std::ostream & os, typedef typename Tr::Full_cell_const_iterator Full_cell_iterator; typedef typename Tr::Full_cell Full_cell; typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator; - + if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3) { std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3."; @@ -158,11 +158,11 @@ export_triangulation_to_off(std::ostream & os, size_t n = tr.number_of_vertices(); std::stringstream output; - + // write the vertices std::map index_of_vertex; int i = 0; - for(Finite_vertex_iterator it = tr.finite_vertices_begin(); + for(Finite_vertex_iterator it = tr.finite_vertices_begin(); it != tr.finite_vertices_end(); ++it, ++i) { Triangulation_IO::output_point(output, tr.geom_traits(), it->point()); @@ -172,7 +172,7 @@ export_triangulation_to_off(std::ostream & os, index_of_vertex[it.base()] = i; } CGAL_assertion( i == n ); - + size_t number_of_triangles = 0; if (tr.maximal_dimension() == 2) { @@ -207,7 +207,7 @@ export_triangulation_to_off(std::ostream & os, output << index_of_vertex[*vit] << " "; } output << std::endl; - ++number_of_triangles; + ++number_of_triangles; } } } @@ -243,7 +243,7 @@ export_triangulation_to_off(std::ostream & os, } os << "OFF \n" - << n << " " + << n << " " << number_of_triangles << " 0\n" << output.str(); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 0d6dc509f9b..1e424d0b1e2 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -42,15 +42,15 @@ class Regular_triangulation { typedef typename RTTraits::Dimension Maximal_dimension_; typedef typename Default::Get< - TDS_, + TDS_, Triangulation_data_structure< Maximal_dimension_, Triangulation_vertex, - Triangulation_full_cell + Triangulation_full_cell > >::type TDS; typedef Triangulation Base; typedef Regular_triangulation Self; - + typedef typename RTTraits::Orientation_d Orientation_d; typedef typename RTTraits::Construct_weighted_point_d Construct_weighted_point_d; typedef typename RTTraits::Power_test_d Power_test_d; @@ -154,7 +154,7 @@ private: } }; public: - + // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS Regular_triangulation(int dim, const Geom_traits &k = Geom_traits()) @@ -163,12 +163,12 @@ public: } // With this constructor, - // the user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension // (= preset_flat_orientation_.first) // It it used by the dark triangulations created by DT::remove Regular_triangulation( - int dim, + int dim, const std::pair &preset_flat_orientation, const Geom_traits &k = Geom_traits()) : Base(dim, preset_flat_orientation, k) @@ -183,8 +183,8 @@ public: Power_test_in_flat_d power_test_in_flat_predicate() const { return Power_test_in_flat_d ( - flat_orientation_, - geom_traits().construct_flat_orientation_d_object(), + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), geom_traits().in_flat_power_test_d_object() ); } @@ -249,13 +249,13 @@ public: return number_of_vertices() - n; } - Vertex_handle insert(const Weighted_point &, - const Locate_type, - const Face &, - const Facet &, + Vertex_handle insert(const Weighted_point &, + const Locate_type, + const Face &, + const Facet &, const Full_cell_handle); - Vertex_handle insert(const Weighted_point & p, + Vertex_handle insert(const Weighted_point & p, const Full_cell_handle start = Full_cell_handle()) { Locate_type lt; @@ -275,14 +275,14 @@ public: Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, const Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle()); - - Vertex_handle insert_if_in_star(const Weighted_point &, - const Vertex_handle, - const Locate_type, - const Face &, - const Facet &, + + Vertex_handle insert_if_in_star(const Weighted_point &, + const Vertex_handle, + const Locate_type, + const Face &, + const Facet &, const Full_cell_handle); - + Vertex_handle insert_if_in_star( const Weighted_point & p, const Vertex_handle star_center, const Full_cell_handle start = Full_cell_handle()) @@ -295,7 +295,7 @@ public: } Vertex_handle insert_if_in_star( - const Weighted_point & p, const Vertex_handle star_center, + const Weighted_point & p, const Vertex_handle star_center, const Vertex_handle hint) { CGAL_assertion( Vertex_handle() != hint ); @@ -351,7 +351,7 @@ public: Orientation o = ori_( boost::make_transform_iterator(s->vertices_begin(), spivi), - boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, spivi)); if( POSITIVE == o ) @@ -380,16 +380,16 @@ public: return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f))); } }; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY - + bool is_valid(bool verbose = false, int level = 0) const; private: - + template bool - does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end, + does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end, Vertex_handle vh) const { // Check all vertices @@ -408,7 +408,7 @@ private: template void - process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, + process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, OutputIterator vertices_out) const { // Get all vertices @@ -428,10 +428,10 @@ private: } } - + template void - process_cz_vertices_after_insertion(InputIterator vertices_begin, + process_cz_vertices_after_insertion(InputIterator vertices_begin, InputIterator vertices_end) { // Get all vertices @@ -459,14 +459,14 @@ private: Conflict_traversal_pred_in_subspace; typedef Conflict_traversal_predicate Conflict_traversal_pred_in_fullspace; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MEMBER VARIABLES std::vector m_hidden_points; }; // class Regular_triangulation -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // FUNCTIONS THAT ARE MEMBER METHODS: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS @@ -541,8 +541,8 @@ Regular_triangulation typedef Triangulation_full_cell< Geom_traits, internal::Triangulation::Dark_full_cell_data > Dark_full_cell_base; - typedef Triangulation_data_structure Dark_tds; typedef Regular_triangulation Dark_triangulation; @@ -661,7 +661,7 @@ Regular_triangulation typedef typename Base::template Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); - + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); // Make the dark simplices in the conflict zone searchable conflict_zone.make_searchable(); @@ -686,8 +686,8 @@ Regular_triangulation dark_incident_s.clear(); dark_out = std::back_inserter(dark_incident_s); dark_side.tds().incident_full_cells(dark_v, dark_out); - for(typename Dark_full_cells::iterator it = dark_incident_s.begin(); - it != dark_incident_s.end(); + for(typename Dark_full_cells::iterator it = dark_incident_s.begin(); + it != dark_incident_s.end(); ++it) { (*it)->data().count_ += 1; @@ -761,7 +761,7 @@ Regular_triangulation int li = light_s->index(dark_s->vertex(di)->data()); Rotor light_r(light_s, li, light_i); typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); - + while( simps.contains(full_cell(light_r)->neighbor(index_of_covertex(light_r))) ) light_r = rotate_rotor(light_r); @@ -871,9 +871,9 @@ Regular_triangulation template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation -::insert_if_in_star(const Weighted_point & p, +::insert_if_in_star(const Weighted_point & p, const Vertex_handle star_center, - const Locate_type lt, const Face & f, const Facet & ft, + const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) { switch( lt ) @@ -915,7 +915,7 @@ Regular_triangulation template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation -::insert_in_conflicting_cell(const Weighted_point & p, +::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s, const Vertex_handle only_if_this_vertex_is_in_the_cz) { @@ -937,10 +937,10 @@ Regular_triangulation cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); - + // Check if the CZ contains "only_if_this_vertex_is_in_the_cz" if (only_if_this_vertex_is_in_the_cz != Vertex_handle() - && !does_cell_range_contain_vertex(cs.begin(), cs.end(), + && !does_cell_range_contain_vertex(cs.begin(), cs.end(), only_if_this_vertex_is_in_the_cz)) { return Vertex_handle(); @@ -949,7 +949,7 @@ Regular_triangulation // Otherwise, proceed with the insertion std::vector cz_vertices; cz_vertices.reserve(64); - process_conflict_zone(cs.begin(), cs.end(), + process_conflict_zone(cs.begin(), cs.end(), std::back_inserter(cz_vertices)); Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft); @@ -1030,8 +1030,8 @@ Regular_triangulation if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), + *this, p, + coaffine_orientation_predicate(), power_test_in_flat_predicate()); return c(s); } @@ -1054,8 +1054,8 @@ Regular_triangulation if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), + *this, p, + coaffine_orientation_predicate(), power_test_in_flat_predicate()); Conflict_traversal_pred_in_subspace tp(*this, c); return tds().gather_full_cells(s, tp, out); @@ -1076,7 +1076,7 @@ template< typename RTTraits, typename TDS > bool Regular_triangulation ::is_valid(bool verbose, int level) const -{ +{ if (!Base::is_valid(verbose, level)) return false; @@ -1087,16 +1087,16 @@ Regular_triangulation cit != finite_full_cells_end() ; ++cit ) { Full_cell_const_handle ch = cit.base(); - for(int i = 0; i < dim+1 ; ++i ) + for(int i = 0; i < dim+1 ; ++i ) { // If the i-th neighbor is not an infinite cell - Vertex_handle opposite_vh = + Vertex_handle opposite_vh = ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); if (!is_infinite(opposite_vh)) { - Power_test_d side = + Power_test_d side = geom_traits().power_test_d_object(); - if (side(Point_const_iterator(ch->vertices_begin()), + if (side(Point_const_iterator(ch->vertices_begin()), Point_const_iterator(ch->vertices_end()), opposite_vh->point()) == ON_POSITIVE_SIDE) { From 8be281a33fb67a396b129b6c60351bfd11a64d5f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Dec 2014 12:56:00 +0100 Subject: [PATCH 138/487] Fix a warning: use std::size_t --- .../test/Tangential_complex/test_utilities.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index c8296211c8d..fde74425301 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -237,18 +237,18 @@ generate_points_on_klein_bottle_variant_5D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(num_points); - int num_cols = num_points/num_lines + 1; + std::size_t num_lines = (std::size_t)sqrt(num_points); + std::size_t num_cols = num_points/num_lines + 1; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) { - int k1 = i / num_lines; - int k2 = i % num_lines; + std::size_t k1 = i / num_lines; + std::size_t k2 = i % num_lines; u = 6.2832 * k1 / num_lines; v = 6.2832 * k2 / num_lines; } From 0e089a2081b7c9f845448fb28208c2364568403c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Dec 2014 17:31:25 +0100 Subject: [PATCH 139/487] Use Power_center for the "star sphere" optimization --- .../include/CGAL/Tangential_complex.h | 61 ++++++++----------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ba60601a65e..ea61c4a2450 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -45,7 +45,6 @@ #include #include -#include #include #include @@ -658,10 +657,13 @@ private: // Triangulation's traits functor & objects typename Tr_traits::Squared_distance_d sqdist = local_tr_traits.squared_distance_d_object(); + typename Tr_traits::Point_weight_d point_weight = + local_tr_traits.point_weight_d_object(); typename Tr_traits::Point_drop_weight_d drop_w = local_tr_traits.point_drop_weight_d_object(); - typename Tr_traits::Center_of_sphere_d center_of_sphere = - local_tr_traits.center_of_sphere_d_object(); + /*typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object();*/ // CJTODO + typename Get_functor::type power_center(local_tr_traits); // Estimate the tangent space const Point ¢er_pt = m_points[i]; @@ -695,6 +697,7 @@ private: // and which contains all the // circumspheres of the star of "center_vertex" boost::optional star_sphere_squared_radius; + FT star_sphere_squared_radius_plus_margin = 0; // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; @@ -709,7 +712,8 @@ private: const Point &neighbor_pt = m_points[neighbor_point_idx]; if (star_sphere_squared_radius - && k_sqdist(center_pt, neighbor_pt) > *star_sphere_squared_radius) + && k_sqdist(center_pt, neighbor_pt) + > star_sphere_squared_radius_plus_margin) break; Tr_point proj_pt = project_point_and_compute_weight( @@ -726,6 +730,12 @@ private: //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) { + // CJTODO TEMP TEST + /*if (star_sphere_squared_radius + && k_sqdist(center_pt, neighbor_pt) + > star_sphere_squared_radius_plus_margin) + std::cout << "ARGGGGGGGH" << std::endl;*/ + vh->data() = neighbor_point_idx; // Let's recompute star_sphere_squared_radius @@ -748,41 +758,24 @@ private: } else { - //********************************* - // We don't compute the circumsphere of the simplex in the - // local tangent plane since it would involve to take the - // weights of the points into account later - // (which is a problem since the ANN is performed on the - // points in the ambient dimension) - // Instead, we compute the subspace defined by the simplex - // and we compute the circumsphere in this subspace - // and we extract the diameter - Tangent_space_basis tsb; - tsb.reserve(Intrinsic_dimension); - Point const& orig = m_points[cell->vertex(0)->data()]; - for (int ii = 1 ; ii <= Intrinsic_dimension ; ++ii) - { - tsb.push_back(k_diff_pts( - m_points[cell->vertex(ii)->data()], orig)); - } - tsb = compute_gram_schmidt_basis(tsb, m_k); - - std::vector proj_pts; - proj_pts.reserve(Intrinsic_dimension + 1); + std::vector cell_pts; + cell_pts.reserve(Intrinsic_dimension + 1); // For each point p for (int ii = 0 ; ii <= Intrinsic_dimension ; ++ii) - { - proj_pts.push_back(project_point( - m_points[cell->vertex(ii)->data()], orig, tsb)); - } + cell_pts.push_back(cell->vertex(ii)->point()); - Tr_bare_point c = center_of_sphere( - proj_pts.begin(), proj_pts.end()); + Tr_point c = power_center(cell_pts.begin(), cell_pts.end()); + FT sq_power_sphere_diam = 4*point_weight(c); - FT sq_circumdiam = 4.*sqdist(c, proj_pts[0]); if (!star_sphere_squared_radius - || sq_circumdiam > *star_sphere_squared_radius) - star_sphere_squared_radius = sq_circumdiam; + || sq_power_sphere_diam > *star_sphere_squared_radius) + { + star_sphere_squared_radius = sq_power_sphere_diam; + star_sphere_squared_radius_plus_margin = + CGAL::sqrt(sq_power_sphere_diam) + 0.5*INPUT_SPARSITY; + star_sphere_squared_radius_plus_margin *= + star_sphere_squared_radius_plus_margin; // squared + } } } } From 1172403b97b1ad9352df4dcc9f110612225abb56 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Dec 2014 12:09:12 +0100 Subject: [PATCH 140/487] Simplify computation of the weight (projected points) --- .../include/CGAL/Tangential_complex.h | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ea61c4a2450..76794af0977 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -710,6 +710,7 @@ private: if (neighbor_point_idx != i) { const Point &neighbor_pt = m_points[neighbor_point_idx]; + FT neighbor_weight = m_weights[neighbor_point_idx]; if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) @@ -717,17 +718,11 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, center_pt, m_tangent_spaces[i], local_tr_traits); + neighbor_pt, neighbor_weight, center_pt, m_tangent_spaces[i], + local_tr_traits); - FT squared_dist_to_tangent_plane = - local_tr_traits.point_weight_d_object()(proj_pt); - FT w = -squared_dist_to_tangent_plane + m_weights[neighbor_point_idx]; - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - drop_w(proj_pt), - w); - - Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); - //Tr_vertex_handle vh = local_tr.insert(wp); + Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); + //Tr_vertex_handle vh = local_tr.insert(proj_pt); if (vh != Tr_vertex_handle()) { // CJTODO TEMP TEST @@ -919,7 +914,7 @@ private: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p Tr_point project_point_and_compute_weight( - const Point &p, const Point &origin, const Tangent_space_basis &ts, + const Point &p, FT w, const Point &origin, const Tangent_space_basis &ts, const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); @@ -953,7 +948,7 @@ private: ( tr_traits.construct_point_d_object()( Intrinsic_dimension, coords.begin(), coords.end()), - m_k.squared_distance_d_object()(p, projected_pt) + w - m_k.squared_distance_d_object()(p, projected_pt) ); } From cd1fe19554e060c939ee9d56cd94c146c3cb3885 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Dec 2014 12:09:42 +0100 Subject: [PATCH 141/487] No need to recompute the tangent plane here --- Tangential_complex/include/CGAL/Tangential_complex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 76794af0977..081d4411e54 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1071,15 +1071,15 @@ private: #ifdef CGAL_LINKED_WITH_TBB if (j == tr_index) { - compute_tangent_triangulation(j); + compute_tangent_triangulation(j, true); } else { Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); - compute_tangent_triangulation(j); + compute_tangent_triangulation(j, true); } #else - compute_tangent_triangulation(j); + compute_tangent_triangulation(j, true); #endif } From 305e02c865598c7da96fb905cfc66dbc8ca569dc Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Dec 2014 18:00:23 +0100 Subject: [PATCH 142/487] Try a new way to solve inconsistencies --- .../include/CGAL/Tangential_complex.h | 120 +++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 081d4411e54..f835510388c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -66,6 +66,19 @@ namespace CGAL { using namespace Tangential_complex_; +class Vertex_data +{ +public: + Vertex_data(std::size_t data = std::numeric_limits::max()) + : m_data(data) + {} + operator std::size_t() { return m_data; } + operator std::size_t() const { return m_data; } + +private: + std::size_t m_data; +}; + /// The class Tangential_complex represents a tangential complex template < typename Kernel, @@ -81,7 +94,7 @@ template < typename Regular_triangulation_euclidean_traits< Epick_d > >::Dimension, Triangulation_vertex > >, std::size_t >, + Epick_d > >, Vertex_data >, Triangulation_full_cell > > > > @@ -448,7 +461,7 @@ public: typedef Delaunay_triangulation + Triangulation_vertex > > DT; typedef typename DT::Vertex_handle DT_VH; typedef typename DT::Finite_full_cell_const_iterator FFC_it; @@ -974,6 +987,8 @@ private: for ( ; it_point_idx != simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; + if (point_idx == std::numeric_limits::max()) + continue; Triangulation const& tr = m_triangulations[point_idx].tr(); Tr_vertex_handle center_vh = m_triangulations[point_idx].center_vertex(); @@ -1037,6 +1052,7 @@ private: Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); + const Tr_traits &local_tr_traits = tr.geom_traits(); std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); @@ -1048,6 +1064,9 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { + +#ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS + std::set c; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) { @@ -1089,6 +1108,103 @@ private: // valid anymore here) break; } +#else + // Inconsistent? + // N.B.: we don't test infinite cells + if (!is_simplex_consistent(*it_c)) + { + // Get the k + 2 closest points + + /*int point_dim = m_k.point_dimension_d_object()(*m_points.begin()); + std::vector center(point_dim, FT(0)); + for (int i = 0 ; i < point_dim ; ++i) + { + for (int j = 0 ; j < Intrinsic_dimension + 1 ; ++j) + { + std::size_t data = (*it_c)->vertex(j)->data(); + const Point &p = m_points[data]; + center[i] += p[i]; + } + center[i] /= (Intrinsic_dimension + 1); + } + Point global_center(center.begin(), center.end());*/ + + std::vector cell_idx; // CJTODO TEMP + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + cell_idx.push_back((*it_c)->vertex(i)->data()); + + std::vector simplex_pts; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + simplex_pts.push_back((*it_c)->vertex(i)->point()); + + //typename Tr_traits::Power_center_d power_center = + // local_tr_traits.power_center_d_object(); // CJTODO + typename Get_functor::type power_center(local_tr_traits); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + + // CJTODO URGENT : que se passe-t-il si c'est un simplex infini ? + Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); + Point global_center = m_points[tr_index]; + const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_center = k_transl( + global_center, + k_scaled_vec(tsb[i], coord(local_center, i))); + } + + KNS_range kns_range = m_points_ds.query_ANN(global_center, Intrinsic_dimension + 2); + std::vector neighbors; + for (KNS_iterator nn_it = kns_range.begin() ; + nn_it != kns_range.end() ; + ++nn_it) + { + neighbors.push_back(nn_it->first); + } + + CGAL::Random rng; + for (std::vector::iterator it = neighbors.begin(); + it != neighbors.end() ; + ++it) + { + m_weights[*it] = + rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + } + + for (std::vector::iterator it = neighbors.begin(); + it != neighbors.end() ; + ++it) + { + std::size_t j = *it; +#ifdef CGAL_LINKED_WITH_TBB + if (j == tr_index) + { + compute_tangent_triangulation(j, true); + } + else + { + Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); + compute_tangent_triangulation(j, true); + } +#else + compute_tangent_triangulation(j, true); +#endif + } + + refresh_tangential_complex(); // CJTODO: heavy computation! + + // We will try the other cells next time (incident_cells is not + // valid anymore here) + break; + } + +#endif } } From a35c173f950311b0d1844c49bc1e7b2709a2dd44 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Dec 2014 18:00:44 +0100 Subject: [PATCH 143/487] Use std::size_t everywhere --- .../test/Tangential_complex/test_utilities.h | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index fde74425301..ac930649b3b 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -76,7 +76,7 @@ std::vector generate_points_on_plane(std::size_t num_p CGAL::Random rng; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT x = rng.get_double(0, 5); FT y = rng.get_double(0, 5); @@ -95,7 +95,7 @@ std::vector generate_points_on_moment_curve( CGAL::Random rng; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT x = rng.get_double(min_x, max_x); std::vector coords; @@ -116,7 +116,7 @@ std::vector generate_points_on_circle_2( CGAL::Random_points_on_circle_2 generator(radius); std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -129,7 +129,7 @@ std::vector generate_points_on_sphere_3( CGAL::Random_points_on_sphere_3 generator(radius); std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -142,7 +142,7 @@ std::vector generate_points_on_sphere_d( CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -157,18 +157,18 @@ std::vector generate_points_on_klein_bottle_3D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(num_points); - int num_cols = num_points/num_lines + 1; + std::size_t num_lines = (std::size_t)sqrt(num_points); + std::size_t num_cols = num_points/num_lines + 1; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) { - int k1 = i / num_lines; - int k2 = i % num_lines; + std::size_t k1 = i / num_lines; + std::size_t k2 = i % num_lines; u = 6.2832 * k1 / num_lines; v = 6.2832 * k2 / num_lines; } @@ -196,18 +196,18 @@ std::vector generate_points_on_klein_bottle_4D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(num_points); - int num_cols = num_points/num_lines + 1; + std::size_t num_lines = (std::size_t)sqrt(num_points); + std::size_t num_cols = num_points/num_lines + 1; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) { - int k1 = i / num_lines; - int k2 = i % num_lines; + std::size_t k1 = i / num_lines; + std::size_t k2 = i % num_lines; u = 6.2832 * k1 / num_lines; v = 6.2832 * k2 / num_lines; } From 2328dbc852d8024752289416c9345c6269b14515 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Dec 2014 18:47:08 +0100 Subject: [PATCH 144/487] Code clean-up & improvements --- .../include/CGAL/Tangential_complex.h | 66 +++++-------------- .../include/CGAL/Tangential_complex/config.h | 11 +++- 2 files changed, 25 insertions(+), 52 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f835510388c..23d78d93c1c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -241,7 +241,8 @@ public: if (boost::is_convertible::value) { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), - Compute_tangent_triangulation(*this, true) + Compute_tangent_triangulation(*this, + true) //tangent_spaces_are_already_computed ); } // Sequential @@ -249,8 +250,12 @@ public: #endif // CGAL_LINKED_WITH_TBB { for (std::size_t i = 0 ; i < m_points.size() ; ++i) - compute_tangent_triangulation(i, true); + { + compute_tangent_triangulation(i, + true); // tangent_spaces_are_already_computed + } } + #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex refreshed in " << t.elapsed() @@ -1084,25 +1089,7 @@ private: rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); } - for (std::set::iterator it=c.begin(); it!=c.end(); ++it) - { - std::size_t j = *it; -#ifdef CGAL_LINKED_WITH_TBB - if (j == tr_index) - { - compute_tangent_triangulation(j, true); - } - else - { - Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); - compute_tangent_triangulation(j, true); - } -#else - compute_tangent_triangulation(j, true); -#endif - } - - refresh_tangential_complex(); // CJTODO: heavy computation! + refresh_tangential_complex(); // We will try the other cells next time (incident_cells is not // valid anymore here) @@ -1110,7 +1097,6 @@ private: } #else // Inconsistent? - // N.B.: we don't test infinite cells if (!is_simplex_consistent(*it_c)) { // Get the k + 2 closest points @@ -1128,10 +1114,6 @@ private: center[i] /= (Intrinsic_dimension + 1); } Point global_center(center.begin(), center.end());*/ - - std::vector cell_idx; // CJTODO TEMP - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - cell_idx.push_back((*it_c)->vertex(i)->data()); std::vector simplex_pts; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) @@ -1148,7 +1130,6 @@ private: typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - // CJTODO URGENT : que se passe-t-il si c'est un simplex infini ? Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; @@ -1159,7 +1140,10 @@ private: k_scaled_vec(tsb[i], coord(local_center, i))); } - KNS_range kns_range = m_points_ds.query_ANN(global_center, Intrinsic_dimension + 2); + KNS_range kns_range = m_points_ds.query_ANN( + global_center, + Intrinsic_dimension + 1 + + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; nn_it != kns_range.end() ; @@ -1176,28 +1160,8 @@ private: m_weights[*it] = rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); } - - for (std::vector::iterator it = neighbors.begin(); - it != neighbors.end() ; - ++it) - { - std::size_t j = *it; -#ifdef CGAL_LINKED_WITH_TBB - if (j == tr_index) - { - compute_tangent_triangulation(j, true); - } - else - { - Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); - compute_tangent_triangulation(j, true); - } -#else - compute_tangent_triangulation(j, true); -#endif - } - - refresh_tangential_complex(); // CJTODO: heavy computation! + + refresh_tangential_complex(); // We will try the other cells next time (incident_cells is not // valid anymore here) @@ -1379,8 +1343,10 @@ private: private: const Kernel m_k; + Points m_points; Weights m_weights; + Points_ds m_points_ds; TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index ce88cf276c4..af37b7e1e47 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -24,14 +24,21 @@ #include //========================= Debugging & profiling ============================= -//#define CGAL_TC_PROFILING +#define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE +// Solving inconsistencies: only change the weights of the inconsistent simplex +// or more? +#define CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS + +// Otherwise... +const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; + //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; -const double INPUT_SPARSITY = 0.5; +const double INPUT_SPARSITY = 0.1; #endif // CGAL_TC_CONFIG_H From 6fd090b634e2af7591d90dfd1f211d5051cdea00 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Dec 2014 18:59:16 +0100 Subject: [PATCH 145/487] Much faster sparsification function --- .../test/Tangential_complex/test_utilities.h | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index ac930649b3b..35fb7f48024 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -38,32 +38,58 @@ sparsify_point_set( const Kernel &k, Point_container const& input_pts, typename Kernel::FT min_squared_dist) { - typedef typename Point_container::value_type Point; - typedef typename CGAL::Tangential_complex_::Point_cloud_data_structure Points_ds; + 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::INS_iterator INS_iterator; + typedef typename Points_ds::INS_range INS_range; typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif - // Create the output container and push the first point into it + // Create the output container std::vector output; - typename Point_container::const_iterator it_pt = input_pts.begin(); - output.push_back(*it_pt); - ++it_pt; + + Points_ds points_ds(input_pts); // Parse the following points, and add them if they are not too close to // the other points - std::size_t c = 1; - for ( ; + std::size_t pt_idx = 0; + for (typename Point_container::const_iterator it_pt = input_pts.begin() ; it_pt != input_pts.end(); - ++it_pt) + ++it_pt, ++pt_idx) { - Points_ds points_ds(output, 0, c); - if (points_ds.query_ANN(*it_pt, 1).begin()->second >= min_squared_dist) + INS_range ins_range = points_ds.query_incremental_ANN(*it_pt); + + // Drop it if there is another point that: + // - is closer that min_squared_dist + // - and has a higher index + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) { - output.push_back(*it_pt); - ++c; + std::size_t neighbor_point_idx = nn_it->first; + typename Kernel::FT sq_dist = nn_it->second; + // The neighbor is further, we keep the point + if (sq_dist >= min_squared_dist) + { + output.push_back(*it_pt); + break; + } + // The neighbor is close and it has a higher index + else if (neighbor_point_idx > pt_idx) + break; // We drop the point + // Otherwise, we go the next closest point } } + +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set sparsified in " << t.elapsed() + << " seconds." << std::endl; +#endif return output; } From 9e48b7caf41e6cfea967e5750580c21dbe26fef4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 11 Dec 2014 18:14:09 +0100 Subject: [PATCH 146/487] Add an insert function to the spatial sorting data structure --- .../include/CGAL/Tangential_complex/Point_cloud.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 5b82f49099f..1e466d65049 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -283,6 +283,13 @@ public: return m_points; }*/ + // Be careful, this function invalidates the tree, + // which will be recomputed at the next query + void insert(std::ptrdiff_t point_idx) + { + m_tree.insert(point_idx); + } + KNS_range query_ANN(const Point &sp, unsigned int k, From e18ba7133cf30a0babbb6b97685179dd01668bd4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 11 Dec 2014 18:17:32 +0100 Subject: [PATCH 147/487] Add an accurate but slow way to generate a sparse point set --- .../include/CGAL/Tangential_complex/config.h | 3 +- .../test_tangential_complex.cpp | 16 +- .../test/Tangential_complex/test_utilities.h | 183 +++++++++++++++--- 3 files changed, 174 insertions(+), 28 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index af37b7e1e47..ba34aaf568e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -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; diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 90f424c7a84..77102284fbd 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -6,13 +6,13 @@ # define TBB_USE_THREADING_TOOL #endif -#include "test_utilities.h" - #include #include #include #include +#include "test_utilities.h" + #include #include @@ -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 points = //generate_points_on_circle_2(NUM_POINTS, 3.); //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); @@ -61,6 +64,11 @@ int main() //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); //generate_points_on_klein_bottle_variant_5D(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)); diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 35fb7f48024..53f6e11980e 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -32,6 +32,56 @@ #include #include +// 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 +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 std::vector sparsify_point_set( @@ -102,11 +152,21 @@ std::vector generate_points_on_plane(std::size_t num_p CGAL::Random rng; std::vector 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 > 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 generate_points_on_moment_curve( CGAL::Random rng; std::vector 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 > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) { FT x = rng.get_double(min_x, max_x); std::vector 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 generate_points_on_circle_2( CGAL::Random_points_on_circle_2 generator(radius); std::vector 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 > 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 generate_points_on_sphere_3( CGAL::Random_points_on_sphere_3 generator(radius); std::vector 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 > 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 generate_points_on_sphere_d( CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector 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 > 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 generate_points_on_klein_bottle_3D( std::vector 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 > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) { FT u, v; if (uniform) @@ -204,10 +313,17 @@ std::vector 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 generate_points_on_klein_bottle_4D( std::vector 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 > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) { FT u, v; if (uniform) @@ -242,11 +361,19 @@ std::vector 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 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 > 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; } From 7a05ab7424a596bbea42cd603e72c82e32120a16 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 10:39:35 +0100 Subject: [PATCH 148/487] Faster "star_sphere" test --- .../include/CGAL/Tangential_complex.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 23d78d93c1c..4759c665cae 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,6 +23,7 @@ #define TANGENTIAL_COMPLEX_H #include +const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; #include #include @@ -715,7 +716,6 @@ private: // and which contains all the // circumspheres of the star of "center_vertex" boost::optional star_sphere_squared_radius; - FT star_sphere_squared_radius_plus_margin = 0; // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; @@ -732,7 +732,7 @@ private: if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > star_sphere_squared_radius_plus_margin) + > *star_sphere_squared_radius + SQ_HALF_SPARSITY) break; Tr_point proj_pt = project_point_and_compute_weight( @@ -746,7 +746,7 @@ private: // CJTODO TEMP TEST /*if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > star_sphere_squared_radius_plus_margin) + > *star_sphere_squared_radius + SQ_HALF_SPARSITY) std::cout << "ARGGGGGGGH" << std::endl;*/ vh->data() = neighbor_point_idx; @@ -784,10 +784,6 @@ private: || sq_power_sphere_diam > *star_sphere_squared_radius) { star_sphere_squared_radius = sq_power_sphere_diam; - star_sphere_squared_radius_plus_margin = - CGAL::sqrt(sq_power_sphere_diam) + 0.5*INPUT_SPARSITY; - star_sphere_squared_radius_plus_margin *= - star_sphere_squared_radius_plus_margin; // squared } } } @@ -1085,8 +1081,7 @@ private: CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) { - m_weights[*it] = - rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); } refresh_tangential_complex(); @@ -1157,8 +1152,7 @@ private: it != neighbors.end() ; ++it) { - m_weights[*it] = - rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); } refresh_tangential_complex(); From 5b13d122f9a8821fd80f9cc2251586a7abf60cb8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:20:27 +0100 Subject: [PATCH 149/487] Bug fix for when the first points lie in a lower dimension --- .../include/CGAL/Regular_triangulation.h | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index b5174b0f698..dceafc44527 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -920,12 +920,26 @@ Regular_triangulation { typedef std::vector Full_cell_h_vector; - Orientation_d ori = geom_traits().orientation_d_object(); - Power_test_d side = geom_traits().power_test_d_object(); - Conflict_pred_in_fullspace c(*this, p, ori, side); + bool is_in_conflict = true; + if( current_dimension() < maximal_dimension() ) + { + Conflict_pred_in_subspace c( + *this, p, + coaffine_orientation_predicate(), + power_test_in_flat_predicate()); + is_in_conflict = c(s); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Power_test_d side = geom_traits().power_test_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + is_in_conflict = c(s); + } + // If p is not in conflict with s, then p is hidden // => we don't insert it - if (!c(s)) + if (!is_in_conflict) { m_hidden_points.push_back(p); return Vertex_handle(); From 1f4015aedf84bf7681c9b3fd5588190209e60456 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:36:27 +0100 Subject: [PATCH 150/487] Added a function to help estimating the intrinsic dimension --- .../include/CGAL/Tangential_complex.h | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 4759c665cae..c74e3fcc64d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -230,6 +230,70 @@ public: << " seconds." << std::endl; #endif } + + void estimate_intrinsic_dimension() + { + const int amb_dim = m_k.point_dimension_d_object()(*m_points.begin()); + + // Kernel functors + typename Kernel::Construct_vector_d constr_vec = + m_k.construct_vector_d_object(); + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename Kernel::Squared_length_d sqlen = + m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Scalar_product_d inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Difference_of_vectors_d diff_vec = + m_k.difference_of_vectors_d_object(); + + std::vector sum_eigen_values(amb_dim, FT(0)); + + Points::const_iterator it_p = m_points.begin(); + Points::const_iterator it_p_end = m_points.end(); + // For each point p + for ( ; it_p != it_p_end ; ++it_p) + { + const Point &p = *it_p; + + KNS_range kns_range = m_points_ds.query_ANN( + p, NUM_POINTS_FOR_PCA, false); + + //******************************* PCA ************************************* + + // One row = one point + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); + KNS_iterator nn_it = kns_range.begin(); + for (int j = 0 ; + j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + ++j, ++nn_it) + { + for (int i = 0 ; i < amb_dim ; ++i) + mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); + } + Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver eig(cov); + + // The eigenvectors are sorted in increasing order of their corresponding + // eigenvalues + Tangent_space_basis ts; + for (int i = 0 ; i < amb_dim ; ++i) + sum_eigen_values[i] += eig.eigenvalues()[i]; + + //************************************************************************* + } + + // CJTODO: replace this by an actual estimation + for (FT v : sum_eigen_values) // CJTODO C++11 + { + std::cout << v << " "; + } + std::cout << "\n"; + } + void refresh_tangential_complex() { From f9bef00845fcf80ddf05238b0d904d867dc233ae Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:37:09 +0100 Subject: [PATCH 151/487] Added load_points_from_file --- .../test/Tangential_complex/test_utilities.h | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 53f6e11980e..6499ef9e207 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -144,6 +144,27 @@ sparsify_point_set( return output; } +template +bool load_points_from_file( + const std::string &filename, OutputIterator points) +{ + std::ifstream in(filename); + if (!in.is_open()) + { + std::cerr << "Could not open '" << filename << "'" << std::endl; + return false; + } + + Point p; + int dim_from_file; + in >> dim_from_file; + + while(in >> p) + *points++ = p; + + return true; +} + template std::vector generate_points_on_plane(std::size_t num_points) { From 8b0993375203c227db2004a86a179ae7bd84757e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:39:15 +0100 Subject: [PATCH 152/487] Forgot to add the StdAfx files --- .../test/Tangential_complex/StdAfx.cpp | 2 ++ Tangential_complex/test/Tangential_complex/StdAfx.h | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 Tangential_complex/test/Tangential_complex/StdAfx.cpp create mode 100644 Tangential_complex/test/Tangential_complex/StdAfx.h diff --git a/Tangential_complex/test/Tangential_complex/StdAfx.cpp b/Tangential_complex/test/Tangential_complex/StdAfx.cpp new file mode 100644 index 00000000000..15668dcadef --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/StdAfx.cpp @@ -0,0 +1,2 @@ +// Build the precompiled headers. +#include "StdAfx.h" \ No newline at end of file diff --git a/Tangential_complex/test/Tangential_complex/StdAfx.h b/Tangential_complex/test/Tangential_complex/StdAfx.h new file mode 100644 index 00000000000..221d2a763cd --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/StdAfx.h @@ -0,0 +1,13 @@ +#ifndef STDAFX_H +#define STDAFX_H + +// CGAL +#include +#include +#include +#include +#include +#include +#include + +#endif //STDAFX_H \ No newline at end of file From 3557c382458a00a3603f125bc8397d331d092a69 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:41:00 +0100 Subject: [PATCH 153/487] Remove unused variables --- Tangential_complex/include/CGAL/Tangential_complex.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c74e3fcc64d..51dc9a41639 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -236,18 +236,8 @@ public: const int amb_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors - typename Kernel::Construct_vector_d constr_vec = - m_k.construct_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = + typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - typename Kernel::Squared_length_d sqlen = - m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = - m_k.scaled_vector_d_object(); - typename Kernel::Scalar_product_d inner_pdct = - m_k.scalar_product_d_object(); - typename Kernel::Difference_of_vectors_d diff_vec = - m_k.difference_of_vectors_d_object(); std::vector sum_eigen_values(amb_dim, FT(0)); From 68a4eb92af1702ea556e64338f6568e1e8232ca1 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 09:21:28 +0100 Subject: [PATCH 154/487] Added the ability to limit the number of points loaded from a file --- .../test/Tangential_complex/test_utilities.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 6499ef9e207..9ada2a42ce9 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -146,7 +146,8 @@ sparsify_point_set( template bool load_points_from_file( - const std::string &filename, OutputIterator points) + const std::string &filename, OutputIterator points, + std::size_t only_first_n_points = std::numeric_limits::max()) { std::ifstream in(filename); if (!in.is_open()) @@ -159,8 +160,12 @@ bool load_points_from_file( int dim_from_file; in >> dim_from_file; - while(in >> p) + std::size_t i = 0; + while(i < only_first_n_points && in >> p) + { *points++ = p; + ++i; + } return true; } From d605eff325b3d53468c4a4c70bf16ec4dbe28d88 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 10:24:44 +0100 Subject: [PATCH 155/487] Restore 4-space identations --- Triangulation/include/CGAL/Triangulation.h | 1914 ++++++++--------- .../CGAL/Triangulation_data_structure.h | 2 +- 2 files changed, 958 insertions(+), 958 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 406a0b5fde7..58fb2548adb 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -50,18 +50,18 @@ public: typedef Point const& result_type; // For result_of Substitute_point_in_vertex_iterator( - Vertex_handle vh_where_point_should_be_substituted, - Point const *subtitute_point) + Vertex_handle vh_where_point_should_be_substituted, + Point const *subtitute_point) : vh_where_point_should_be_substituted_(vh_where_point_should_be_substituted) , subtitute_point_(subtitute_point) {} result_type operator()(Vertex_handle vh) const { - if (vh == vh_where_point_should_be_substituted_) - return *subtitute_point_; - else - return vh->point(); + if (vh == vh_where_point_should_be_substituted_) + return *subtitute_point_; + else + return vh->point(); } private: @@ -74,682 +74,682 @@ private: template < class TriangulationTraits, class TDS_ = Default > class Triangulation { - typedef typename TriangulationTraits::Dimension Maximal_dimension_; - typedef typename Default::Get, - Triangulation_full_cell > - >::type TDS; - typedef Triangulation Self; - -protected: - typedef typename TriangulationTraits::Flat_orientation_d Flat_orientation_d; - typedef typename TriangulationTraits::Construct_flat_orientation_d Construct_flat_orientation_d; - typedef typename TriangulationTraits::In_flat_orientation_d In_flat_orientation_d; - - // Wrapper - struct Coaffine_orientation_d - { - boost::optional* fop; - Construct_flat_orientation_d cfo; - In_flat_orientation_d ifo; - - Coaffine_orientation_d( - boost::optional& x, - Construct_flat_orientation_d const&y, - In_flat_orientation_d const&z) - : fop(&x), cfo(y), ifo(z) {} + typedef typename TriangulationTraits::Dimension Maximal_dimension_; + typedef typename Default::Get, + Triangulation_full_cell > + >::type TDS; + typedef Triangulation Self; - template - CGAL::Orientation operator()(Iter a, Iter b) const +protected: + typedef typename TriangulationTraits::Flat_orientation_d Flat_orientation_d; + typedef typename TriangulationTraits::Construct_flat_orientation_d Construct_flat_orientation_d; + typedef typename TriangulationTraits::In_flat_orientation_d In_flat_orientation_d; + + // Wrapper + struct Coaffine_orientation_d { - if (*fop) - return ifo(fop->get(),a,b); - *fop = cfo(a,b); - CGAL_assertion(ifo(fop->get(),a,b) == CGAL::POSITIVE); - return CGAL::POSITIVE; - } - }; + boost::optional* fop; + Construct_flat_orientation_d cfo; + In_flat_orientation_d ifo; - void reset_flat_orientation() - { - if (current_dimension() == preset_flat_orientation_.first) + Coaffine_orientation_d( + boost::optional& x, + Construct_flat_orientation_d const&y, + In_flat_orientation_d const&z) + : fop(&x), cfo(y), ifo(z) {} + + template + CGAL::Orientation operator()(Iter a, Iter b) const + { + if (*fop) + return ifo(fop->get(),a,b); + *fop = cfo(a,b); + CGAL_assertion(ifo(fop->get(),a,b) == CGAL::POSITIVE); + return CGAL::POSITIVE; + } + }; + + void reset_flat_orientation() { - CGAL_assertion(preset_flat_orientation_.second != NULL); - flat_orientation_ = *preset_flat_orientation_.second; + if (current_dimension() == preset_flat_orientation_.first) + { + CGAL_assertion(preset_flat_orientation_.second != NULL); + flat_orientation_ = *preset_flat_orientation_.second; + } + else + flat_orientation_ = boost::none; } - else - flat_orientation_ = boost::none; - } - typedef typename TriangulationTraits::Orientation_d - Orientation_d; + typedef typename TriangulationTraits::Orientation_d + Orientation_d; public: - typedef TriangulationTraits Geom_traits; - typedef TDS Triangulation_ds; + typedef TriangulationTraits Geom_traits; + typedef TDS Triangulation_ds; - typedef typename TDS::Vertex Vertex; - typedef typename TDS::Full_cell Full_cell; - typedef typename TDS::Facet Facet; - typedef typename TDS::Face Face; + typedef typename TDS::Vertex Vertex; + typedef typename TDS::Full_cell Full_cell; + typedef typename TDS::Facet Facet; + typedef typename TDS::Face Face; - typedef Maximal_dimension_ Maximal_dimension; - typedef typename Geom_traits::Point_d Point; + typedef Maximal_dimension_ Maximal_dimension; + typedef typename Geom_traits::Point_d Point; - typedef typename TDS::Vertex_handle Vertex_handle; - typedef typename TDS::Vertex_iterator Vertex_iterator; - typedef typename TDS::Vertex_const_handle Vertex_const_handle; - typedef typename TDS::Vertex_const_iterator Vertex_const_iterator; + typedef typename TDS::Vertex_handle Vertex_handle; + typedef typename TDS::Vertex_iterator Vertex_iterator; + typedef typename TDS::Vertex_const_handle Vertex_const_handle; + typedef typename TDS::Vertex_const_iterator Vertex_const_iterator; - typedef typename TDS::Full_cell_handle Full_cell_handle; - typedef typename TDS::Full_cell_iterator Full_cell_iterator; - typedef typename TDS::Full_cell_const_handle Full_cell_const_handle; - typedef typename TDS::Full_cell_const_iterator Full_cell_const_iterator; - - typedef typename TDS::Facet_iterator Facet_iterator; + typedef typename TDS::Full_cell_handle Full_cell_handle; + typedef typename TDS::Full_cell_iterator Full_cell_iterator; + typedef typename TDS::Full_cell_const_handle Full_cell_const_handle; + typedef typename TDS::Full_cell_const_iterator Full_cell_const_iterator; + + typedef typename TDS::Facet_iterator Facet_iterator; - typedef typename TDS::size_type size_type; - typedef typename TDS::difference_type difference_type; + typedef typename TDS::size_type size_type; + typedef typename TDS::difference_type difference_type; - /// The type of location a new point is found lying on - enum Locate_type - { - ON_VERTEX = 0 // simplex of dimension 0 - , IN_FACE = 1 // simplex of dimension in [ 1, |current_dimension()| - 2 ] - , IN_FACET = 2 // simplex of dimension |current_dimension()| - 1 - , IN_FULL_CELL = 3 /// simplex of dimension |current_dimension()| - , OUTSIDE_CONVEX_HULL = 4 - , OUTSIDE_AFFINE_HULL = 5 - }; + /// The type of location a new point is found lying on + enum Locate_type + { + ON_VERTEX = 0 // simplex of dimension 0 + , IN_FACE = 1 // simplex of dimension in [ 1, |current_dimension()| - 2 ] + , IN_FACET = 2 // simplex of dimension |current_dimension()| - 1 + , IN_FULL_CELL = 3 /// simplex of dimension |current_dimension()| + , OUTSIDE_CONVEX_HULL = 4 + , OUTSIDE_AFFINE_HULL = 5 + }; - // Finite elements iterators + // Finite elements iterators - class Finiteness_predicate; + class Finiteness_predicate; - typedef boost::filter_iterator - Finite_vertex_iterator; - typedef boost::filter_iterator - Finite_vertex_const_iterator; - typedef boost::filter_iterator - Finite_full_cell_iterator; - typedef boost::filter_iterator - Finite_full_cell_const_iterator; - typedef boost::filter_iterator - Finite_facet_iterator; + typedef boost::filter_iterator + Finite_vertex_iterator; + typedef boost::filter_iterator + Finite_vertex_const_iterator; + typedef boost::filter_iterator + Finite_full_cell_iterator; + typedef boost::filter_iterator + Finite_full_cell_const_iterator; + typedef boost::filter_iterator + Finite_facet_iterator; protected: // DATA MEMBERS - Triangulation_ds tds_; - const Geom_traits kernel_; - Vertex_handle infinity_; - mutable std::vector orientations_; - mutable boost::optional flat_orientation_; - // The user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension - // (= preset_flat_orientation_.first) - // preset_flat_orientation_.first = numeric_limits::max() otherwise) - std::pair preset_flat_orientation_; - // for stochastic walk in the locate() function: - mutable Random rng_; + Triangulation_ds tds_; + const Geom_traits kernel_; + Vertex_handle infinity_; + mutable std::vector orientations_; + mutable boost::optional flat_orientation_; + // The user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // preset_flat_orientation_.first = numeric_limits::max() otherwise) + std::pair preset_flat_orientation_; + // for stochastic walk in the locate() function: + mutable Random rng_; #ifdef CGAL_TRIANGULATION_STATISTICS - mutable unsigned long walk_size_; + mutable unsigned long walk_size_; #endif protected: // HELPER FUNCTIONS - typedef CGAL::Iterator_project< - typename Full_cell::Vertex_handle_const_iterator, - internal::Triangulation::Point_from_vertex_handle - > Point_const_iterator; + typedef CGAL::Iterator_project< + typename Full_cell::Vertex_handle_const_iterator, + internal::Triangulation::Point_from_vertex_handle + > Point_const_iterator; - Point_const_iterator points_begin(Full_cell_const_handle c) const - { return Point_const_iterator(c->vertices_begin()); } - Point_const_iterator points_end(Full_cell_const_handle c) const - { return Point_const_iterator(c->vertices_end()); } - Point_const_iterator points_begin(Full_cell_handle c) const - { return Point_const_iterator(c->vertices_begin()); } - Point_const_iterator points_end(Full_cell_handle c) const - { return Point_const_iterator(c->vertices_end()); } + Point_const_iterator points_begin(Full_cell_const_handle c) const + { return Point_const_iterator(c->vertices_begin()); } + Point_const_iterator points_end(Full_cell_const_handle c) const + { return Point_const_iterator(c->vertices_end()); } + Point_const_iterator points_begin(Full_cell_handle c) const + { return Point_const_iterator(c->vertices_begin()); } + Point_const_iterator points_end(Full_cell_handle c) const + { return Point_const_iterator(c->vertices_end()); } public: - // FACETS OPERATIONS + // FACETS OPERATIONS - Full_cell_handle full_cell(const Facet & f) const - { - return tds().full_cell(f); - } + Full_cell_handle full_cell(const Facet & f) const + { + return tds().full_cell(f); + } - int index_of_covertex(const Facet & f) const - { - return tds().index_of_covertex(f); - } - + int index_of_covertex(const Facet & f) const + { + return tds().index_of_covertex(f); + } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UTILITIES - // A co-dimension 2 sub-simplex. called a Rotor because we can rotate - // the two "covertices" around the sub-simplex. Useful for traversing the - // boundary of a hole. NOT DOCUMENTED - typedef cpp11::tuple Rotor; - Full_cell_handle full_cell(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<0>(r); - } - int index_of_covertex(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<1>(r); - } - int index_of_second_covertex(const Rotor & r) const // NOT DOCUMENTED - { - return cpp11::get<2>(r); - } - Rotor rotate_rotor(Rotor & r) // NOT DOCUMENTED... - { - int opposite = full_cell(r)->mirror_index(index_of_covertex(r)); - Full_cell_handle s = full_cell(r)->neighbor(index_of_covertex(r)); - int new_second = s->index(full_cell(r)->vertex(index_of_second_covertex(r))); - return Rotor(s, new_second, opposite); - } - - // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS - - Triangulation(int dim, const Geom_traits &k = Geom_traits()) - : tds_(dim) - , kernel_(k) - , infinity_() - , preset_flat_orientation_((std::numeric_limits::max)(), NULL) - , rng_((long)0) -#ifdef CGAL_TRIANGULATION_STATISTICS - ,walk_size_(0) -#endif - { - clear(); - } - - // With this constructor, - // the user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension - // (= preset_flat_orientation_.first) - // It it used for by dark triangulations created by DT::remove - Triangulation( - int dim, - const std::pair &preset_flat_orientation, - const Geom_traits &k = Geom_traits()) - : tds_(dim) - , kernel_(k) - , infinity_() - , preset_flat_orientation_(preset_flat_orientation) - , rng_((long)0) -#ifdef CGAL_TRIANGULATION_STATISTICS - ,walk_size_(0) -#endif - { - clear(); - } - - Triangulation(const Triangulation & t2) - : tds_(t2.tds_) - , kernel_(t2.kernel_) - , infinity_() - , preset_flat_orientation_((std::numeric_limits::max()), NULL) - , rng_(t2.rng_) -#ifdef CGAL_TRIANGULATION_STATISTICS - ,walk_size_(t2.walk_size_) -#endif - { - // We find the vertex at infinity by scanning the vertices of both - // triangulations. This works because Compact_container garantees that - // the vertices in the copy (*this) are stored in the same order as in - // the original triangulation (t2) - infinity_ = vertices_begin(); - Vertex_const_iterator inf2 = t2.vertices_begin(); - while( inf2 != t2.infinite_vertex() ) + // A co-dimension 2 sub-simplex. called a Rotor because we can rotate + // the two "covertices" around the sub-simplex. Useful for traversing the + // boundary of a hole. NOT DOCUMENTED + typedef cpp11::tuple Rotor; + Full_cell_handle full_cell(const Rotor & r) const // NOT DOCUMENTED { - ++infinity_; - ++inf2; + return cpp11::get<0>(r); + } + int index_of_covertex(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<1>(r); + } + int index_of_second_covertex(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<2>(r); + } + Rotor rotate_rotor(Rotor & r) // NOT DOCUMENTED... + { + int opposite = full_cell(r)->mirror_index(index_of_covertex(r)); + Full_cell_handle s = full_cell(r)->neighbor(index_of_covertex(r)); + int new_second = s->index(full_cell(r)->vertex(index_of_second_covertex(r))); + return Rotor(s, new_second, opposite); } - // A full_cell has at most 1 + maximal_dimension() facets: - orientations_.resize(1 + maximal_dimension()); - // Our coaffine orientation predicates HAS state member variables - reset_flat_orientation(); - } - ~Triangulation() {} + // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS FUNCTIONS + Triangulation(int dim, const Geom_traits k = Geom_traits()) + : tds_(dim) + , kernel_(k) + , infinity_() + , preset_flat_orientation_(std::numeric_limits::max(), NULL) + , rng_((long)0) +#ifdef CGAL_TRIANGULATION_STATISTICS + ,walk_size_(0) +#endif + { + clear(); + } - /* These three function are no longer needed since we do not use them anymore - in the Delaunay_triangulation::remove. *But*, they may reappear in the future - if we manage to passe the information that flags/TDS_data is available or not - for marking simplices in Delaunay_triangulation::remove. This would be useful - to make it a little faster, instead of binary searching if a simplex is marked - or not... - // NOT DOCUMENTED -- - bool get_visited(Full_cell_handle s) const - { - return tds().get_visited(s); - } - // NOT DOCUMENTED -- - bool get_visited(Full_cell_const_handle s) const - { - return tds().get_visited(s); - } + // With this constructor, + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // It it used for by dark triangulations created by DT::remove + Triangulation( + int dim, + const std::pair &preset_flat_orientation, + const Geom_traits k = Geom_traits()) + : tds_(dim) + , kernel_(k) + , infinity_() + , preset_flat_orientation_(preset_flat_orientation) + , rng_((long)0) +#ifdef CGAL_TRIANGULATION_STATISTICS + ,walk_size_(0) +#endif + { + clear(); + } + + Triangulation(const Triangulation & t2) + : tds_(t2.tds_) + , kernel_(t2.kernel_) + , infinity_() + , preset_flat_orientation_(std::numeric_limits::max(), NULL) + , rng_(t2.rng_) +#ifdef CGAL_TRIANGULATION_STATISTICS + ,walk_size_(t2.walk_size_) +#endif + { + // We find the vertex at infinity by scanning the vertices of both + // triangulations. This works because Compact_container garantees that + // the vertices in the copy (*this) are stored in the same order as in + // the original triangulation (t2) + infinity_ = vertices_begin(); + Vertex_const_iterator inf2 = t2.vertices_begin(); + while( inf2 != t2.infinite_vertex() ) + { + ++infinity_; + ++inf2; + } + // A full_cell has at most 1 + maximal_dimension() facets: + orientations_.resize(1 + maximal_dimension()); + // Our coaffine orientation predicates HAS state member variables + reset_flat_orientation(); + } - // NOT DOCUMENTED -- - void set_visited(Full_cell_handle s, bool b) const - { - tds().set_visited(s, b); - } */ + ~Triangulation() {} - Coaffine_orientation_d coaffine_orientation_predicate() const - { - return Coaffine_orientation_d ( - flat_orientation_, - geom_traits().construct_flat_orientation_d_object(), - geom_traits().in_flat_orientation_d_object() - ); - } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS FUNCTIONS - const Triangulation_ds & tds() const - { - return tds_; - } + /* These three function are no longer needed since we do not use them anymore + in the Delaunay_triangulation::remove. *But*, they may reappear in the future + if we manage to passe the information that flags/TDS_data is available or not + for marking simplices in Delaunay_triangulation::remove. This would be useful + to make it a little faster, instead of binary searching if a simplex is marked + or not... + // NOT DOCUMENTED -- + bool get_visited(Full_cell_handle s) const + { + return tds().get_visited(s); + } + // NOT DOCUMENTED -- + bool get_visited(Full_cell_const_handle s) const + { + return tds().get_visited(s); + } - Triangulation_ds & tds() - { - return tds_; - } + // NOT DOCUMENTED -- + void set_visited(Full_cell_handle s, bool b) const + { + tds().set_visited(s, b); + } */ - const Geom_traits & geom_traits() const - { - return kernel_; - } + Coaffine_orientation_d coaffine_orientation_predicate() const + { + return Coaffine_orientation_d ( + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), + geom_traits().in_flat_orientation_d_object() + ); + } - int maximal_dimension() const { return tds().maximal_dimension(); } - int current_dimension() const { return tds().current_dimension(); } + const Triangulation_ds & tds() const + { + return tds_; + } - bool empty() const - { - return current_dimension() == -1; - } + Triangulation_ds & tds() + { + return tds_; + } - size_type number_of_vertices() const - { - return tds().number_of_vertices() - 1; - } + const Geom_traits & geom_traits() const + { + return kernel_; + } - size_type number_of_full_cells() const - { - return tds().number_of_full_cells(); - } + int maximal_dimension() const { return tds().maximal_dimension(); } + int current_dimension() const { return tds().current_dimension(); } - Vertex_handle infinite_vertex() const - { - return infinity_; - } + bool empty() const + { + return current_dimension() == -1; + } - Full_cell_handle infinite_full_cell() const - { - CGAL_assertion(infinite_vertex()->full_cell()->has_vertex(infinite_vertex())); - return infinite_vertex()->full_cell(); - } + size_type number_of_vertices() const + { + return tds().number_of_vertices() - 1; + } + + size_type number_of_full_cells() const + { + return tds().number_of_full_cells(); + } + + Vertex_handle infinite_vertex() const + { + return infinity_; + } + + Full_cell_handle infinite_full_cell() const + { + CGAL_assertion(infinite_vertex()->full_cell()->has_vertex(infinite_vertex())); + return infinite_vertex()->full_cell(); + } // - - - - - - - - - - - - - - - - - - - - - - - - - NON CONSTANT-TIME ACCESS FUNCTIONS - size_type number_of_finite_full_cells() const - { - Full_cell_const_iterator s = full_cells_begin(); - size_type result = number_of_full_cells(); - for( ; s != full_cells_end(); ++s ) + size_type number_of_finite_full_cells() const { - if( is_infinite(s) ) - --result; + Full_cell_const_iterator s = full_cells_begin(); + size_type result = number_of_full_cells(); + for( ; s != full_cells_end(); ++s ) + { + if( is_infinite(s) ) + --result; + } + return result; } - return result; - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRAVERSAL - Vertex_iterator vertices_begin() { return tds().vertices_begin(); } - Vertex_iterator vertices_end() { return tds().vertices_end(); } + Vertex_iterator vertices_begin() { return tds().vertices_begin(); } + Vertex_iterator vertices_end() { return tds().vertices_end(); } - Vertex_const_iterator vertices_begin() const { return tds().vertices_begin(); } - Vertex_const_iterator vertices_end() const { return tds().vertices_end(); } + Vertex_const_iterator vertices_begin() const { return tds().vertices_begin(); } + Vertex_const_iterator vertices_end() const { return tds().vertices_end(); } - Finite_vertex_iterator finite_vertices_begin() - { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } - Finite_vertex_iterator finite_vertices_end() - { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } - Finite_vertex_const_iterator finite_vertices_begin() const - { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } - Finite_vertex_const_iterator finite_vertices_end() const - { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } + Finite_vertex_iterator finite_vertices_begin() + { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } + Finite_vertex_iterator finite_vertices_end() + { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } + Finite_vertex_const_iterator finite_vertices_begin() const + { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } + Finite_vertex_const_iterator finite_vertices_end() const + { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } - Full_cell_iterator full_cells_begin() { return tds().full_cells_begin(); } - Full_cell_iterator full_cells_end() { return tds().full_cells_end(); } + Full_cell_iterator full_cells_begin() { return tds().full_cells_begin(); } + Full_cell_iterator full_cells_end() { return tds().full_cells_end(); } - Full_cell_const_iterator full_cells_begin() const { return tds().full_cells_begin(); } - Full_cell_const_iterator full_cells_end() const { return tds().full_cells_end(); } + Full_cell_const_iterator full_cells_begin() const { return tds().full_cells_begin(); } + Full_cell_const_iterator full_cells_end() const { return tds().full_cells_end(); } - Finite_full_cell_iterator finite_full_cells_begin() - { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } - Finite_full_cell_iterator finite_full_cells_end() - { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } - Finite_full_cell_const_iterator finite_full_cells_begin() const - { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } - Finite_full_cell_const_iterator finite_full_cells_end() const - { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } + Finite_full_cell_iterator finite_full_cells_begin() + { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } + Finite_full_cell_iterator finite_full_cells_end() + { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } + Finite_full_cell_const_iterator finite_full_cells_begin() const + { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } + Finite_full_cell_const_iterator finite_full_cells_end() const + { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } - Facet_iterator facets_begin() { return tds().facets_begin(); } - Facet_iterator facets_end() { return tds().facets_end(); } - Facet_iterator finite_facets_begin() - { return Finite_facet_iterator(Finiteness_predicate(*this), facets_begin(), facets_end()); } - Facet_iterator finite_facets_end() - { return Finite_facet_iterator(Finiteness_predicate(*this), facets_end(), facets_end()); } + Facet_iterator facets_begin() { return tds().facets_begin(); } + Facet_iterator facets_end() { return tds().facets_end(); } + Facet_iterator finite_facets_begin() + { return Finite_facet_iterator(Finiteness_predicate(*this), facets_begin(), facets_end()); } + Facet_iterator finite_facets_end() + { return Finite_facet_iterator(Finiteness_predicate(*this), facets_end(), facets_end()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SOME PREDICATE FUNCTORS - class Finiteness_predicate - { - const Self & t_; - public: - Finiteness_predicate(const Self & t) : t_(t) {} - template < class T > - bool operator()(const T & t) const + class Finiteness_predicate { - return ! t_.is_infinite(t); - } - }; + const Self & t_; + public: + Finiteness_predicate(const Self & t) : t_(t) {} + template < class T > + bool operator()(const T & t) const + { + return ! t_.is_infinite(t); + } + }; - class Point_equality_predicate - { - const Point & o_; - public: - Point_equality_predicate(const Point & o) : o_(o) {} - bool operator()(const Point & o) const { return (o == o_ );} - }; + class Point_equality_predicate + { + const Point & o_; + public: + Point_equality_predicate(const Point & o) : o_(o) {} + bool operator()(const Point & o) const { return (o == o_ );} + }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SIMPLE QUERIES /* - bool is_vertex(const Point & p, Vertex_handle & v, Full_cell_handle hint = Full_cell_handle()) const - { - Locate_type lt; - Face f(maximal_dimension()); - Facet ft; - Full_cell_handle s = locate(p, lt, f, ft, hint); - if( ON_VERTEX == lt ) + bool is_vertex(const Point & p, Vertex_handle & v, Full_cell_handle hint = Full_cell_handle()) const { - v = s->vertex(f.index(0)); - return true; + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, hint); + if( ON_VERTEX == lt ) + { + v = s->vertex(f.index(0)); + return true; + } + return false; } - return false; - } - bool is_vertex(Vertex_const_handle v) const - { - return tds().is_vertex(v); - } + bool is_vertex(Vertex_const_handle v) const + { + return tds().is_vertex(v); + } - bool is_full_cell(Full_cell_const_handle s) const - { - return tds().is_full_cell(s); - } + bool is_full_cell(Full_cell_const_handle s) const + { + return tds().is_full_cell(s); + } */ - bool is_infinite(Vertex_const_handle v) const - { - CGAL_precondition(Vertex_const_handle() != v); - return (infinite_vertex() == v); - } - - bool is_infinite(const Vertex & v) const /* internal use, not documented */ - { - return (&(*infinite_vertex()) == &v); - } - - bool is_infinite(Full_cell_const_handle s) const - { - CGAL_precondition(Full_cell_const_handle() != s); - return is_infinite(*s); - } - bool is_infinite(const Full_cell & s) const /* internal use, not documented */ - { - for(int i = 0; i <= current_dimension(); ++i) - if( is_infinite(s.vertex(i)) ) - return true; - return false; - } - bool is_infinite(const Facet & ft) const - { - Full_cell_const_handle s = full_cell(ft); - CGAL_precondition(s != Full_cell_handle()); - if( is_infinite(s) ) - return (s->vertex(index_of_covertex(ft)) != infinite_vertex()); - return false; - } - - bool is_infinite(const Face & f) const - { - Full_cell_const_handle s = f.full_cell(); - CGAL_precondition(s != Full_cell_handle()); - if( is_infinite(s) ) + bool is_infinite(Vertex_const_handle v) const { - Vertex_handle v; - for( int i(0); i<= f.face_dimension(); ++i) - if ( is_infinite( f.vertex(i) )) return true; + CGAL_precondition(Vertex_const_handle() != v); + return (infinite_vertex() == v); } - return false; - } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ELEMENT GATHERING - - - template< typename OutputIterator > - OutputIterator incident_full_cells(const Face & f, OutputIterator out) const - { - return tds().incident_full_cells(f, out); - } - template< typename OutputIterator > - OutputIterator incident_full_cells(Vertex_const_handle v, OutputIterator out) const - { - return tds().incident_full_cells(v, out); - } - template< typename OutputIterator > - OutputIterator star(const Face & f, OutputIterator out) const - { - return tds().star(f, out); - } - - template< typename OutputIterator > - OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) - { - return tds().incident_faces(v, d, out); - } - /* - template< typename OutputIterator, class Comparator > - OutputIterator incident_upper_faces( Vertex_const_handle v, int d, - OutputIterator out, Comparator cmp = Comparator()) - { - return tds().incident_upper_faces(v, d, out, cmp); - } - template< typename OutputIterator > - OutputIterator incident_upper_faces( Vertex_const_handle v, int d, - OutputIterator out) - { // FIXME: uncomment this function, since it uses a comparator specific to - // *geometric* triangulation (taking infinite vertex into account) - internal::Triangulation::Compare_vertices_for_upper_face cmp(*this); - return tds().incident_upper_faces(v, d, out, cmp); - } - */ - Orientation orientation(Full_cell_const_handle s, bool in_is_valid = false) const - { - if( ! in_is_valid ) - CGAL_assertion( ! is_infinite(s) ); - if( 0 == current_dimension() ) - return POSITIVE; - if( current_dimension() == maximal_dimension() ) + bool is_infinite(const Vertex & v) const /* internal use, not documented */ { - Orientation_d ori = geom_traits().orientation_d_object(); - return ori(points_begin(s), points_begin(s) + 1 + current_dimension()); + return (&(*infinite_vertex()) == &v); } - else + + bool is_infinite(Full_cell_const_handle s) const { - return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); + CGAL_precondition(Full_cell_const_handle() != s); + return is_infinite(*s); + } + bool is_infinite(const Full_cell & s) const /* internal use, not documented */ + { + for(int i = 0; i <= current_dimension(); ++i) + if( is_infinite(s.vertex(i)) ) + return true; + return false; + } + bool is_infinite(const Facet & ft) const + { + Full_cell_const_handle s = full_cell(ft); + CGAL_precondition(s != Full_cell_handle()); + if( is_infinite(s) ) + return (s->vertex(index_of_covertex(ft)) != infinite_vertex()); + return false; + } + + bool is_infinite(const Face & f) const + { + Full_cell_const_handle s = f.full_cell(); + CGAL_precondition(s != Full_cell_handle()); + if( is_infinite(s) ) + { + Vertex_handle v; + for( int i(0); i<= f.face_dimension(); ++i) + if ( is_infinite( f.vertex(i) )) return true; + } + return false; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ELEMENT GATHERING + + + template< typename OutputIterator > + OutputIterator incident_full_cells(const Face & f, OutputIterator out) const + { + return tds().incident_full_cells(f, out); + } + template< typename OutputIterator > + OutputIterator incident_full_cells(Vertex_const_handle v, OutputIterator out) const + { + return tds().incident_full_cells(v, out); + } + template< typename OutputIterator > + OutputIterator star(const Face & f, OutputIterator out) const + { + return tds().star(f, out); + } + + template< typename OutputIterator > + OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) + { + return tds().incident_faces(v, d, out); + } + /* + template< typename OutputIterator, class Comparator > + OutputIterator incident_upper_faces( Vertex_const_handle v, int d, + OutputIterator out, Comparator cmp = Comparator()) + { + return tds().incident_upper_faces(v, d, out, cmp); + } + template< typename OutputIterator > + OutputIterator incident_upper_faces( Vertex_const_handle v, int d, + OutputIterator out) + { // FIXME: uncomment this function, since it uses a comparator specific to + // *geometric* triangulation (taking infinite vertex into account) + internal::Triangulation::Compare_vertices_for_upper_face cmp(*this); + return tds().incident_upper_faces(v, d, out, cmp); + } + */ + Orientation orientation(Full_cell_const_handle s, bool in_is_valid = false) const + { + if( ! in_is_valid ) + CGAL_assertion( ! is_infinite(s) ); + if( 0 == current_dimension() ) + return POSITIVE; + if( current_dimension() == maximal_dimension() ) + { + Orientation_d ori = geom_traits().orientation_d_object(); + return ori(points_begin(s), points_begin(s) + 1 + current_dimension()); + } + else + { + return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); + } } - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UPDATE OPERATIONS - void clear() - { - tds_.clear(); - infinity_ = tds().insert_increase_dimension(); - // A full_cell has at most 1 + maximal_dimension() facets: - orientations_.resize(1 + maximal_dimension()); - // Our coaffine orientation predicates HAS state member variables - reset_flat_orientation(); + void clear() + { + tds_.clear(); + infinity_ = tds().insert_increase_dimension(); + // A full_cell has at most 1 + maximal_dimension() facets: + orientations_.resize(1 + maximal_dimension()); + // Our coaffine orientation predicates HAS state member variables + reset_flat_orientation(); #ifdef CGAL_TRIANGULATION_STATISTICS - walk_size_ = 0; + walk_size_ = 0; #endif - } + } - void set_current_dimension(int d) - { - tds().set_current_dimension(d); - } + void set_current_dimension(int d) + { + tds().set_current_dimension(d); + } - Full_cell_handle new_full_cell() - { - return tds().new_full_cell(); - } + Full_cell_handle new_full_cell() + { + return tds().new_full_cell(); + } - Vertex_handle new_vertex(const Point & p) - { - return tds().new_vertex(p); - } + Vertex_handle new_vertex(const Point & p) + { + return tds().new_vertex(p); + } - void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) - { - tds().set_neighbors(s, i, s1, j); - } + void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) + { + tds().set_neighbors(s, i, s1, j); + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY - bool is_valid(bool = false, int = 0) const; - bool are_incident_full_cells_valid(Vertex_const_handle, bool = false, int = 0) const; + bool is_valid(bool = false, int = 0) const; + bool are_incident_full_cells_valid(Vertex_const_handle, bool = false, int = 0) const; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POINT LOCATION protected: - template< typename OrientationPredicate > - Full_cell_handle do_locate( const Point &, Locate_type &, Face &, Facet &, - Full_cell_handle start, - const OrientationPredicate & o) const; + template< typename OrientationPredicate > + Full_cell_handle do_locate( const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle start, + const OrientationPredicate & o) const; public: - Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, - Full_cell_handle start = Full_cell_handle()) const; - Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, - Vertex_handle) const; - Full_cell_handle locate(const Point & p, Full_cell_handle s = Full_cell_handle()) const; - Full_cell_handle locate(const Point & p, Vertex_handle v) const; + Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle start = Full_cell_handle()) const; + Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, + Vertex_handle) const; + Full_cell_handle locate(const Point & p, Full_cell_handle s = Full_cell_handle()) const; + Full_cell_handle locate(const Point & p, Vertex_handle v) const; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS - Vertex_handle contract_face(const Point &, const Face &); + Vertex_handle contract_face(const Point &, const Face &); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POINT INSERTION - template< typename ForwardIterator > - size_type insert(ForwardIterator start, ForwardIterator end) - { - size_type n = number_of_vertices(); - std::vector points(start, end); - spatial_sort(points.begin(), points.end(), geom_traits()); - Full_cell_handle hint = Full_cell_handle(); - typename std::vector::const_iterator s = points.begin(); - while( s != points.end() ) + template< typename ForwardIterator > + size_type insert(ForwardIterator start, ForwardIterator end) { - hint = insert(*s++, hint)->full_cell(); + size_type n = number_of_vertices(); + std::vector points(start, end); + spatial_sort(points.begin(), points.end(), geom_traits()); + Full_cell_handle hint = Full_cell_handle(); + typename std::vector::const_iterator s = points.begin(); + while( s != points.end() ) + { + hint = insert(*s++, hint)->full_cell(); + } + return number_of_vertices() - n; } - return number_of_vertices() - n; - } - Vertex_handle insert(const Point &, const Locate_type, const Face &, const Facet &, const Full_cell_handle); - Vertex_handle insert(const Point &, Full_cell_handle start = Full_cell_handle()); - Vertex_handle insert(const Point &, Vertex_handle); - template< typename ForwardIterator > - Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft) - { - Emptyset_iterator out; - return insert_in_hole(p, start, end, ft, out); - } - template< typename ForwardIterator, typename OutputIterator > - Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft, - OutputIterator out) - { - Vertex_handle v = tds().insert_in_hole(start, end, ft, out); - v->set_point(p); - return v; - } - Vertex_handle insert_in_face(const Point &, const Face &); - Vertex_handle insert_in_facet(const Point &, const Facet &); - Vertex_handle insert_in_full_cell(const Point &, Full_cell_handle); - Vertex_handle insert_outside_convex_hull_1(const Point &, Full_cell_handle); - Vertex_handle insert_outside_convex_hull(const Point &, Full_cell_handle); - Vertex_handle insert_outside_affine_hull(const Point &); + Vertex_handle insert(const Point &, const Locate_type, const Face &, const Facet &, const Full_cell_handle); + Vertex_handle insert(const Point &, Full_cell_handle start = Full_cell_handle()); + Vertex_handle insert(const Point &, Vertex_handle); + template< typename ForwardIterator > + Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft) + { + Emptyset_iterator out; + return insert_in_hole(p, start, end, ft, out); + } + template< typename ForwardIterator, typename OutputIterator > + Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft, + OutputIterator out) + { + Vertex_handle v = tds().insert_in_hole(start, end, ft, out); + v->set_point(p); + return v; + } + Vertex_handle insert_in_face(const Point &, const Face &); + Vertex_handle insert_in_facet(const Point &, const Facet &); + Vertex_handle insert_in_full_cell(const Point &, Full_cell_handle); + Vertex_handle insert_outside_convex_hull_1(const Point &, Full_cell_handle); + Vertex_handle insert_outside_convex_hull(const Point &, Full_cell_handle); + Vertex_handle insert_outside_affine_hull(const Point &); // - - - - - - - - - - - - - - - - - - - - - - - - - - - FACET-TRAVERSAL PREDICATES - template< typename OrientationPredicate > - class Outside_convex_hull_traversal_predicate - { - Triangulation & t_; - const Point & p_; - OrientationPredicate const& ori_; - int cur_dim_; - public: - Outside_convex_hull_traversal_predicate(Triangulation & t, const Point & p, - OrientationPredicate const& ori) - : t_(t), p_(p), ori_(ori), cur_dim_(t.current_dimension()) {} - // FUTURE change parameter to const reference - bool operator()(Facet f) const + template< typename OrientationPredicate > + class Outside_convex_hull_traversal_predicate { - Full_cell_handle s = t_.full_cell(f); - const int i = t_.index_of_covertex(f); - Full_cell_handle n = s->neighbor(i); - if( ! t_.is_infinite(n) ) - return false; - // FIXME: infinite vertex is NOT at index 0 a priori. - n->vertex(0)->set_point(p_); - bool ok = (POSITIVE == ori_(t_.points_begin(n), t_.points_begin(n) + cur_dim_ + 1)); - return ok; - } - }; + Triangulation & t_; + const Point & p_; + OrientationPredicate const& ori_; + int cur_dim_; + public: + Outside_convex_hull_traversal_predicate(Triangulation & t, const Point & p, + OrientationPredicate const& ori) + : t_(t), p_(p), ori_(ori), cur_dim_(t.current_dimension()) {} + // FUTURE change parameter to const reference + bool operator()(Facet f) const + { + Full_cell_handle s = t_.full_cell(f); + const int i = t_.index_of_covertex(f); + Full_cell_handle n = s->neighbor(i); + if( ! t_.is_infinite(n) ) + return false; + // FIXME: infinite vertex is NOT at index 0 a priori. + n->vertex(0)->set_point(p_); + bool ok = (POSITIVE == ori_(t_.points_begin(n), t_.points_begin(n) + cur_dim_ + 1)); + return ok; + } + }; - // make sure all full_cells have positive orientation - void reorient_full_cells(); + // make sure all full_cells have positive orientation + void reorient_full_cells(); protected: // This is used in the |remove(v)| member function to manage sets of Full_cell_handles template< typename FCH > struct Full_cell_set : public std::vector { - typedef std::vector Base_set; - using Base_set::begin; - using Base_set::end; - void make_searchable() - { // sort the full cell handles - std::sort(begin(), end()); - } - bool contains(const FCH & fch) const - { - return std::binary_search(begin(), end(), fch); - } - bool contains_1st_and_not_2nd(const FCH & fst, const FCH & snd) const - { - return ( ! contains(snd) ) && ( contains(fst) ); - } + typedef std::vector Base_set; + using Base_set::begin; + using Base_set::end; + void make_searchable() + { // sort the full cell handles + std::sort(begin(), end()); + } + bool contains(const FCH & fch) const + { + return std::binary_search(begin(), end(), fch); + } + bool contains_1st_and_not_2nd(const FCH & fst, const FCH & snd) const + { + return ( ! contains(snd) ) && ( contains(fst) ); + } }; }; // Triangulation<...> @@ -763,20 +763,20 @@ void Triangulation ::reorient_full_cells() { - if( current_dimension() < 1 ) - return; - Full_cell_iterator sit = full_cells_begin(); - Full_cell_iterator send = full_cells_end(); - while( sit != send ) - { - if( is_infinite(sit) && (1 == current_dimension()) ) + if( current_dimension() < 1 ) + return; + Full_cell_iterator sit = full_cells_begin(); + Full_cell_iterator send = full_cells_end(); + while( sit != send ) { - ++sit; - continue; + if( is_infinite(sit) && (1 == current_dimension()) ) + { + ++sit; + continue; + } + sit->swap_vertices(current_dimension() - 1, current_dimension()); + ++sit; } - sit->swap_vertices(current_dimension() - 1, current_dimension()); - ++sit; - } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -787,11 +787,11 @@ typename Triangulation::Vertex_handle Triangulation ::contract_face(const Point & p, const Face & f) { - CGAL_precondition( ! is_infinite(f) ); - Vertex_handle v = tds().contract_face(f); - v->set_point(p); - CGAL_expensive_postcondition_msg(are_incident_full_cells_valid(v), "new point is not where it should be"); - return v; + CGAL_precondition( ! is_infinite(f) ); + Vertex_handle v = tds().contract_face(f); + v->set_point(p); + CGAL_expensive_postcondition_msg(are_incident_full_cells_valid(v), "new point is not where it should be"); + return v; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -802,32 +802,32 @@ typename Triangulation::Vertex_handle Triangulation ::insert(const Point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) { - switch( lt ) - { - case IN_FULL_CELL: - return insert_in_full_cell(p, s); - break; - case OUTSIDE_CONVEX_HULL: - return insert_outside_convex_hull(p, s); - break; - case OUTSIDE_AFFINE_HULL: - return insert_outside_affine_hull(p); - break; - case IN_FACET: + switch( lt ) { - return insert_in_facet(p, ft); - break; + case IN_FULL_CELL: + return insert_in_full_cell(p, s); + break; + case OUTSIDE_CONVEX_HULL: + return insert_outside_convex_hull(p, s); + break; + case OUTSIDE_AFFINE_HULL: + return insert_outside_affine_hull(p); + break; + case IN_FACET: + { + return insert_in_facet(p, ft); + break; + } + case IN_FACE: + return insert_in_face(p, f); + break; + case ON_VERTEX: + s->vertex(f.index(0))->set_point(p); + return s->vertex(f.index(0)); + break; } - case IN_FACE: - return insert_in_face(p, f); - break; - case ON_VERTEX: - s->vertex(f.index(0))->set_point(p); - return s->vertex(f.index(0)); - break; - } - CGAL_assertion(false); - return Vertex_handle(); + CGAL_assertion(false); + return Vertex_handle(); } template < class TT, class TDS > @@ -835,11 +835,11 @@ typename Triangulation::Vertex_handle Triangulation ::insert(const Point & p, Full_cell_handle start) { - Locate_type lt; - Face f(maximal_dimension()); - Facet ft; - Full_cell_handle s = locate(p, lt, f, ft, start); - return insert(p, lt, f, ft, s); + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, start); + return insert(p, lt, f, ft, s); } template < class TT, class TDS > @@ -847,9 +847,9 @@ typename Triangulation::Vertex_handle Triangulation ::insert(const Point & p, Vertex_handle v) { - if( Vertex_handle() == v ) - v = infinite_vertex(); - return insert(p, v->full_cell()); + if( Vertex_handle() == v ) + v = infinite_vertex(); + return insert(p, v->full_cell()); } template < class TT, class TDS > @@ -857,10 +857,10 @@ typename Triangulation::Vertex_handle Triangulation ::insert_in_face(const Point & p, const Face & f) { - CGAL_precondition( ! is_infinite(f) ); - Vertex_handle v = tds().insert_in_face(f); - v->set_point(p); - return v; + CGAL_precondition( ! is_infinite(f) ); + Vertex_handle v = tds().insert_in_face(f); + v->set_point(p); + return v; } template < class TT, class TDS > @@ -868,10 +868,10 @@ typename Triangulation::Vertex_handle Triangulation ::insert_in_facet(const Point & p, const Facet & ft) { - CGAL_precondition( ! is_infinite(ft) ); - Vertex_handle v = tds().insert_in_facet(ft); - v->set_point(p); - return v; + CGAL_precondition( ! is_infinite(ft) ); + Vertex_handle v = tds().insert_in_facet(ft); + v->set_point(p); + return v; } template < class TT, class TDS > @@ -879,10 +879,10 @@ typename Triangulation::Vertex_handle Triangulation ::insert_in_full_cell(const Point & p, Full_cell_handle s) { - CGAL_precondition( ! is_infinite(s) ); - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - return v; + CGAL_precondition( ! is_infinite(s) ); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + return v; } // NOT DOCUMENTED... @@ -891,20 +891,20 @@ typename Triangulation::Vertex_handle Triangulation ::insert_outside_convex_hull_1(const Point & p, Full_cell_handle s) { - // This is a special case for dimension 1, because in that case, the right - // infinite full_cell is not correctly oriented... (sice its first vertex is the - // infinite one... - CGAL_precondition( is_infinite(s) ); - CGAL_precondition( 1 == current_dimension() ); - // FIXME: infinite vertex is NOT at index 0 a priori. But I'm not sure it's a problem here. - bool swap = (0 == s->neighbor(0)->index(s)); - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - if( swap ) - { - s->swap_vertices(0, 1); - } - return v; + // This is a special case for dimension 1, because in that case, the right + // infinite full_cell is not correctly oriented... (sice its first vertex is the + // infinite one... + CGAL_precondition( is_infinite(s) ); + CGAL_precondition( 1 == current_dimension() ); + // FIXME: infinite vertex is NOT at index 0 a priori. But I'm not sure it's a problem here. + bool swap = (0 == s->neighbor(0)->index(s)); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + if( swap ) + { + s->swap_vertices(0, 1); + } + return v; } template < class TT, class TDS > @@ -912,31 +912,31 @@ typename Triangulation::Vertex_handle Triangulation ::insert_outside_convex_hull(const Point & p, Full_cell_handle s) { - if( 1 == current_dimension() ) - { - return insert_outside_convex_hull_1(p, s); - } - CGAL_precondition( is_infinite(s) ); - CGAL_assertion( current_dimension() >= 2 ); - std::vector simps; - simps.reserve(64); - std::back_insert_iterator > out(simps); - if( current_dimension() < maximal_dimension() ) - { - Outside_convex_hull_traversal_predicate - ochtp(*this, p, coaffine_orientation_predicate()); - tds().gather_full_cells(s, ochtp, out); - } - else - { - Orientation_d ori = geom_traits().orientation_d_object(); - Outside_convex_hull_traversal_predicate - ochtp(*this, p, ori); - tds().gather_full_cells(s, ochtp, out); - } - // FIXME: infinite vertex is NOT at index 0 a priori. - Vertex_handle v = insert_in_hole(p, simps.begin(), simps.end(), Facet(s, 0)); - return v; + if( 1 == current_dimension() ) + { + return insert_outside_convex_hull_1(p, s); + } + CGAL_precondition( is_infinite(s) ); + CGAL_assertion( current_dimension() >= 2 ); + std::vector simps; + simps.reserve(64); + std::back_insert_iterator > out(simps); + if( current_dimension() < maximal_dimension() ) + { + Outside_convex_hull_traversal_predicate + ochtp(*this, p, coaffine_orientation_predicate()); + tds().gather_full_cells(s, ochtp, out); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Outside_convex_hull_traversal_predicate + ochtp(*this, p, ori); + tds().gather_full_cells(s, ochtp, out); + } + // FIXME: infinite vertex is NOT at index 0 a priori. + Vertex_handle v = insert_in_hole(p, simps.begin(), simps.end(), Facet(s, 0)); + return v; } template < class TT, class TDS > @@ -944,21 +944,21 @@ typename Triangulation::Vertex_handle Triangulation ::insert_outside_affine_hull(const Point & p) { - CGAL_precondition( current_dimension() < maximal_dimension() ); - Vertex_handle v = tds().insert_increase_dimension(infinite_vertex()); - // reset the orientation predicate: - reset_flat_orientation(); - v->set_point(p); - if( current_dimension() >= 1 ) - { - // FIXME: infinite vertex is NOT at index 0 a priori. - Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); - Orientation o = orientation(s); - CGAL_assertion( COPLANAR != o ); - if( NEGATIVE == o ) - reorient_full_cells(); - } - return v; + CGAL_precondition( current_dimension() < maximal_dimension() ); + Vertex_handle v = tds().insert_increase_dimension(infinite_vertex()); + // reset the orientation predicate: + reset_flat_orientation(); + v->set_point(p); + if( current_dimension() >= 1 ) + { + // FIXME: infinite vertex is NOT at index 0 a priori. + Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Orientation o = orientation(s); + CGAL_assertion( COPLANAR != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + } + return v; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -969,181 +969,181 @@ template< typename OrientationPredicate > typename Triangulation::Full_cell_handle Triangulation ::do_locate( const Point & p, // query point - Locate_type & loc_type,// type of result (full_cell, face, vertex) - Face & face,// the face containing the query in its interior (when appropriate) - Facet & facet,// the facet containing the query in its interior (when appropriate) - const Full_cell_handle start// starting full_cell for the walk - , OrientationPredicate const& orientation_pred - ) const + Locate_type & loc_type,// type of result (full_cell, face, vertex) + Face & face,// the face containing the query in its interior (when appropriate) + Facet & facet,// the facet containing the query in its interior (when appropriate) + const Full_cell_handle start// starting full_cell for the walk + , OrientationPredicate const& orientation_pred + ) const { - const int cur_dim = current_dimension(); + const int cur_dim = current_dimension(); - if( cur_dim == -1 ) - { - loc_type = OUTSIDE_AFFINE_HULL; - return Full_cell_handle(); - } - else if( cur_dim == 0 ) - { - Vertex_handle vit = infinite_full_cell()->neighbor(0)->vertex(0); - if( EQUAL != geom_traits().compare_lexicographically_d_object()(p, vit->point()) ) + if( cur_dim == -1 ) { - loc_type = OUTSIDE_AFFINE_HULL; - return Full_cell_handle(); + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); } + else if( cur_dim == 0 ) + { + Vertex_handle vit = infinite_full_cell()->neighbor(0)->vertex(0); + if( EQUAL != geom_traits().compare_lexicographically_d_object()(p, vit->point()) ) + { + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); + } + else + { + loc_type = ON_VERTEX; + face.set_full_cell(vit->full_cell()); + face.set_index(0, 0); + return vit->full_cell(); + } + } + + Full_cell_handle s; + + // if we don't know where to start, we start from any bounded full_cell + if( Full_cell_handle() == start ) + // THE HACK THAT NOBODY SHOULD DO... BUT DIFFICULT TO WORK AROUND + // THIS... TODO: WORK AROUND IT + // FIXME: infinite vertex is NOT at index 0 a priori. + s = const_cast(this)->infinite_full_cell()->neighbor(0); else { - loc_type = ON_VERTEX; - face.set_full_cell(vit->full_cell()); - face.set_index(0, 0); - return vit->full_cell(); + s = start; + if( is_infinite(s) ) + s = s->neighbor(0); // FIXME: index of infinite vertex is not zero ( not 0) } - } - Full_cell_handle s; - - // if we don't know where to start, we start from any bounded full_cell - if( Full_cell_handle() == start ) - // THE HACK THAT NOBODY SHOULD DO... BUT DIFFICULT TO WORK AROUND - // THIS... TODO: WORK AROUND IT - // FIXME: infinite vertex is NOT at index 0 a priori. - s = const_cast(this)->infinite_full_cell()->neighbor(0); - else - { - s = start; - if( is_infinite(s) ) - s = s->neighbor(0); // FIXME: index of infinite vertex is not zero ( not 0) - } - - // Check if query |p| is outside the affine hull - if( cur_dim < maximal_dimension() ) - { - if( ! geom_traits().contained_in_affine_hull_d_object()( - points_begin(s), - points_begin(s) + current_dimension() + 1, - p) ) + // Check if query |p| is outside the affine hull + if( cur_dim < maximal_dimension() ) { - loc_type = OUTSIDE_AFFINE_HULL; - return Full_cell_handle(); + if( ! geom_traits().contained_in_affine_hull_d_object()( + points_begin(s), + points_begin(s) + current_dimension() + 1, + p) ) + { + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); + } } - } - // we remember the |previous|ly visited full_cell to avoid the evaluation - // of one |orientation| predicate - Full_cell_handle previous = Full_cell_handle(); - bool full_cell_not_found = true; - while(full_cell_not_found) // we walk until we locate the query point |p| - { - #ifdef CGAL_TRIANGULATION_STATISTICS - ++walk_size_; - #endif - // For the remembering stochastic walk, we need to start trying - // with a random index: - int j, i = rng_.get_int(0, cur_dim); - // we check |p| against all the full_cell's hyperplanes in turn - - for(j = 0; j <= cur_dim; ++j, i = (i + 1) % (cur_dim + 1) ) + // we remember the |previous|ly visited full_cell to avoid the evaluation + // of one |orientation| predicate + Full_cell_handle previous = Full_cell_handle(); + bool full_cell_not_found = true; + while(full_cell_not_found) // we walk until we locate the query point |p| { - Full_cell_handle next = s->neighbor(i); - if( previous == next ) - { // no need to compute the orientation, we already know it - orientations_[i] = POSITIVE; - continue; // go to next full_cell's facet - } + #ifdef CGAL_TRIANGULATION_STATISTICS + ++walk_size_; + #endif + // For the remembering stochastic walk, we need to start trying + // with a random index: + int j, i = rng_.get_int(0, cur_dim); + // we check |p| against all the full_cell's hyperplanes in turn + + for(j = 0; j <= cur_dim; ++j, i = (i + 1) % (cur_dim + 1) ) + { + Full_cell_handle next = s->neighbor(i); + if( previous == next ) + { // no need to compute the orientation, we already know it + orientations_[i] = POSITIVE; + continue; // go to next full_cell's facet + } - Substitute_point_in_vertex_iterator< - typename Full_cell::Vertex_handle_const_iterator> - spivi(s->vertex(i), &p); + Substitute_point_in_vertex_iterator< + typename Full_cell::Vertex_handle_const_iterator> + spivi(s->vertex(i), &p); - orientations_[i] = orientation_pred( - boost::make_transform_iterator(s->vertices_begin(), spivi), - boost::make_transform_iterator(s->vertices_begin() + cur_dim + 1, - spivi)); + orientations_[i] = orientation_pred( + boost::make_transform_iterator(s->vertices_begin(), spivi), + boost::make_transform_iterator(s->vertices_begin() + cur_dim + 1, + spivi)); - if( orientations_[i] != NEGATIVE ) - { - // from this facet's point of view, we are inside the - // full_cell or on its boundary, so we continue to next facet - continue; - } + if( orientations_[i] != NEGATIVE ) + { + // from this facet's point of view, we are inside the + // full_cell or on its boundary, so we continue to next facet + continue; + } - // At this point, we know that we have to jump to the |next| - // full_cell because orientation_[i] == NEGATIVE - previous = s; - s = next; - if( is_infinite(next) ) - { // we have arrived OUTSIDE the convex hull of the triangulation, - // so we stop the search - full_cell_not_found = false; - loc_type = OUTSIDE_CONVEX_HULL; + // At this point, we know that we have to jump to the |next| + // full_cell because orientation_[i] == NEGATIVE + previous = s; + s = next; + if( is_infinite(next) ) + { // we have arrived OUTSIDE the convex hull of the triangulation, + // so we stop the search + full_cell_not_found = false; + loc_type = OUTSIDE_CONVEX_HULL; + face.set_full_cell(s); + } + break; + } // end of the 'for' loop + if( ( cur_dim + 1 ) == j ) // we found the full_cell containing |p| + full_cell_not_found = false; + } + // Here, we know in which full_cell |p| is in. + // We now check more precisely where |p| landed: + // vertex, facet, face or full_cell. + if( ! is_infinite(s) ) + { face.set_full_cell(s); - } - break; - } // end of the 'for' loop - if( ( cur_dim + 1 ) == j ) // we found the full_cell containing |p| - full_cell_not_found = false; - } - // Here, we know in which full_cell |p| is in. - // We now check more precisely where |p| landed: - // vertex, facet, face or full_cell. - if( ! is_infinite(s) ) - { - face.set_full_cell(s); - int num(0); - int verts(0); - for(int i = 0; i < cur_dim; ++i) - { - if( orientations_[i] == COPLANAR ) - { - ++num; - facet = Facet(s, i); - } - else - face.set_index(verts++, i); + int num(0); + int verts(0); + for(int i = 0; i < cur_dim; ++i) + { + if( orientations_[i] == COPLANAR ) + { + ++num; + facet = Facet(s, i); + } + else + face.set_index(verts++, i); + } + //-- We could put the if{}else{} below in the loop above, but then we would + // need to test if (verts < cur_dim) many times... we do it only once + // here: + if( orientations_[cur_dim] == COPLANAR ) + { + ++num; + facet = Facet(s, cur_dim); + } + else if( verts < cur_dim ) + face.set_index(verts, cur_dim); + //-- end of remark above // + if( 0 == num ) + { + loc_type = IN_FULL_CELL; + face.clear(); + } + else if( cur_dim == num ) + loc_type = ON_VERTEX; + else if( 1 == num ) + loc_type = IN_FACET; + else + loc_type = IN_FACE; } - //-- We could put the if{}else{} below in the loop above, but then we would - // need to test if (verts < cur_dim) many times... we do it only once - // here: - if( orientations_[cur_dim] == COPLANAR ) - { - ++num; - facet = Facet(s, cur_dim); - } - else if( verts < cur_dim ) - face.set_index(verts, cur_dim); - //-- end of remark above // - if( 0 == num ) - { - loc_type = IN_FULL_CELL; - face.clear(); - } - else if( cur_dim == num ) - loc_type = ON_VERTEX; - else if( 1 == num ) - loc_type = IN_FACET; - else - loc_type = IN_FACE; - } - return s; + return s; } template < class TT, class TDS > typename Triangulation::Full_cell_handle Triangulation ::locate( const Point & p, // query point - Locate_type & loc_type,// type of result (full_cell, face, vertex) - Face & face,// the face containing the query in its interior (when appropriate) - Facet & facet,// the facet containing the query in its interior (when appropriate) - Full_cell_handle start// starting full_cell for the walk - ) const + Locate_type & loc_type,// type of result (full_cell, face, vertex) + Face & face,// the face containing the query in its interior (when appropriate) + Facet & facet,// the facet containing the query in its interior (when appropriate) + Full_cell_handle start// starting full_cell for the walk + ) const { - if( current_dimension() == maximal_dimension() ) - { - Orientation_d ori = geom_traits().orientation_d_object(); - return do_locate(p, loc_type, face, facet, start, ori); - } - else - return do_locate(p, loc_type, face, facet, start, coaffine_orientation_predicate()); + if( current_dimension() == maximal_dimension() ) + { + Orientation_d ori = geom_traits().orientation_d_object(); + return do_locate(p, loc_type, face, facet, start, ori); + } + else + return do_locate(p, loc_type, face, facet, start, coaffine_orientation_predicate()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1153,14 +1153,14 @@ template < class TT, class TDS > typename Triangulation::Full_cell_handle Triangulation ::locate( const Point & p, - Locate_type & loc_type, - Face & face, - Facet & facet, - Vertex_handle start) const + Locate_type & loc_type, + Face & face, + Facet & facet, + Vertex_handle start) const { - if( Vertex_handle() == start ) - start = infinite_vertex(); - return locate(p, loc_type, face, facet, start->full_cell()); + if( Vertex_handle() == start ) + start = infinite_vertex(); + return locate(p, loc_type, face, facet, start->full_cell()); } template < class TT, class TDS > @@ -1168,10 +1168,10 @@ typename Triangulation::Full_cell_handle Triangulation ::locate(const Point & p, Full_cell_handle s) const { - Locate_type lt; - Face face(maximal_dimension()); - Facet facet; - return locate(p, lt, face, facet, s); + Locate_type lt; + Face face(maximal_dimension()); + Facet facet; + return locate(p, lt, face, facet, s); } template < class TT, class TDS > @@ -1179,9 +1179,9 @@ typename Triangulation::Full_cell_handle Triangulation ::locate(const Point & p, Vertex_handle v) const { - if( Vertex_handle() != v ) - v = infinite_vertex(); - return this->locate(p, v->full_cell()); + if( Vertex_handle() != v ) + v = infinite_vertex(); + return this->locate(p, v->full_cell()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY @@ -1191,71 +1191,71 @@ bool Triangulation ::is_valid(bool verbose, int level) const { - if( ! tds().is_valid(verbose, level) ) - return false; + if( ! tds().is_valid(verbose, level) ) + return false; - Full_cell_const_iterator c; - if( current_dimension() < 0 ) + Full_cell_const_iterator c; + if( current_dimension() < 0 ) + return true; + Orientation o; + for( c = full_cells_begin(); c != full_cells_end(); ++c ) + { + if( is_infinite(c) ) + { + if( current_dimension() > 1 ) + { + int i = c->index( infinite_vertex() ); + Full_cell_handle n = c->neighbor(i); + infinite_vertex()->set_point(n->vertex(c->mirror_index(i))->point()); + o = - orientation(c, true); + } + else + o = POSITIVE; + } + else + o = orientation(c, true); + if( NEGATIVE == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); + return false; + } + if( COPLANAR == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); + return false; + } + } return true; - Orientation o; - for( c = full_cells_begin(); c != full_cells_end(); ++c ) - { - if( is_infinite(c) ) - { - if( current_dimension() > 1 ) - { - int i = c->index( infinite_vertex() ); - Full_cell_handle n = c->neighbor(i); - infinite_vertex()->set_point(n->vertex(c->mirror_index(i))->point()); - o = - orientation(c, true); - } - else - o = POSITIVE; - } - else - o = orientation(c, true); - if( NEGATIVE == o ) - { - if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); - return false; - } - if( COPLANAR == o ) - { - if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); - return false; - } - } - return true; } template < class TT, class TDS > bool Triangulation::are_incident_full_cells_valid(Vertex_const_handle v, bool verbose, int) const { - if( current_dimension() <= 0 ) + if( current_dimension() <= 0 ) + return true; + typedef std::vector Simps; + Simps simps; + simps.reserve(64); + std::back_insert_iterator out(simps); + incident_full_cells(v, out); + typename Simps::const_iterator sit = simps.begin(); + for( ; sit != simps.end(); ++sit ) + { + if( is_infinite(*sit) ) + continue; + Orientation o = orientation(*sit); + if( NEGATIVE == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); + return false; + } + if( COPLANAR == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); + return false; + } + } return true; - typedef std::vector Simps; - Simps simps; - simps.reserve(64); - std::back_insert_iterator out(simps); - incident_full_cells(v, out); - typename Simps::const_iterator sit = simps.begin(); - for( ; sit != simps.end(); ++sit ) - { - if( is_infinite(*sit) ) - continue; - Orientation o = orientation(*sit); - if( NEGATIVE == o ) - { - if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); - return false; - } - if( COPLANAR == o ) - { - if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); - return false; - } - } - return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1274,43 +1274,43 @@ operator>>(std::istream & is, Triangulation & tr) // of vertices, plus the non combinatorial information on each full_cell // - the neighbors of each full_cell by their index in the preceding list { - typedef Triangulation T; - typedef typename T::Vertex_handle Vertex_handle; + typedef Triangulation T; + typedef typename T::Vertex_handle Vertex_handle; - // read current dimension and number of vertices - size_t n; - int cd; - if( is_ascii(is) ) - is >> cd >> n; - else - { - read(is, cd); - read(is, n, io_Read_write()); - } + // read current dimension and number of vertices + size_t n; + int cd; + if( is_ascii(is) ) + is >> cd >> n; + else + { + read(is, cd); + read(is, n, io_Read_write()); + } - CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation has too high dimension"); + CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation has too high dimension"); - tr.clear(); - tr.set_current_dimension(cd); + tr.clear(); + tr.set_current_dimension(cd); - if( n == 0 ) - return is; + if( n == 0 ) + return is; - std::vector vertices; - vertices.resize(n+1); - vertices[0] = tr.infinite_vertex(); - is >> (*vertices[0]); + std::vector vertices; + vertices.resize(n+1); + vertices[0] = tr.infinite_vertex(); + is >> (*vertices[0]); - // read the vertices: - size_t i(1); - while( i <= n ) - { - vertices[i] = tr.new_vertex(); - is >> (*vertices[i]); // read a vertex - ++i; - } + // read the vertices: + size_t i(1); + while( i <= n ) + { + vertices[i] = tr.new_vertex(); + is >> (*vertices[i]); // read a vertex + ++i; + } - // now, read the combinatorial information + // now, read the combinatorial information return tr.tds().read_full_cells(is, vertices); } @@ -1326,41 +1326,41 @@ operator<<(std::ostream & os, const Triangulation & tr) // of vertices, plus the non combinatorial information on each full_cell // - the neighbors of each full_cell by their index in the preceding list { - typedef Triangulation T; - typedef typename T::Vertex_const_handle Vertex_handle; - typedef typename T::Vertex_const_iterator Vertex_iterator; + typedef Triangulation T; + typedef typename T::Vertex_const_handle Vertex_handle; + typedef typename T::Vertex_const_iterator Vertex_iterator; - // outputs dimensions and number of vertices - size_t n = tr.number_of_vertices(); - if( is_ascii(os) ) - os << tr.current_dimension() << std::endl << n << std::endl; - else - { - write(os, tr.current_dimension()); - write(os, n, io_Read_write()); - } + // outputs dimensions and number of vertices + size_t n = tr.number_of_vertices(); + if( is_ascii(os) ) + os << tr.current_dimension() << std::endl << n << std::endl; + else + { + write(os, tr.current_dimension()); + write(os, n, io_Read_write()); + } - if( n == 0 ) - return os; + if( n == 0 ) + return os; - size_t i(0); - // write the vertices - std::map index_of_vertex; + size_t i(0); + // write the vertices + std::map index_of_vertex; - // infinite vertex has index 0 (among all the vertices) - index_of_vertex[tr.infinite_vertex()] = i++; - os << *tr.infinite_vertex(); - for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it ) - { - if( tr.is_infinite(it) ) - continue; - os << *it; // write the vertex - index_of_vertex[it] = i++; - } - CGAL_assertion( i == n+1 ); + // infinite vertex has index 0 (among all the vertices) + index_of_vertex[tr.infinite_vertex()] = i++; + os << *tr.infinite_vertex(); + for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it ) + { + if( tr.is_infinite(it) ) + continue; + os << *it; // write the vertex + index_of_vertex[it] = i++; + } + CGAL_assertion( i == n+1 ); - // output the combinatorial information - return tr.tds().write_full_cells(os, index_of_vertex); + // output the combinatorial information + return tr.tds().write_full_cells(os, index_of_vertex); } } //namespace CGAL diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 16b7d6917c9..52b57d24262 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -1597,7 +1597,7 @@ operator<<(std::ostream & os, const Triangulation_data_structure std::size_t i = 0; for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it, ++i ) { - os << *it << std::endl; // write the vertex + os << *it << std::endl; // write the vertex index_of_vertex[it] = i; } CGAL_assertion( i == n ); From b11c4cc8ffae1a8bcdbcc0c51e4c086cc2dcc0a6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 20:26:02 +0100 Subject: [PATCH 156/487] Add a benchmark --- .../Tangential_complex/CMakeLists.txt | 77 ++++++ .../benchmark/Tangential_complex/StdAfx.cpp | 2 + .../benchmark/Tangential_complex/StdAfx.h | 14 ++ .../Tangential_complex/XML_exporter.h | 236 ++++++++++++++++++ .../Tangential_complex/benchmark_tc.cpp | 216 ++++++++++++++++ 5 files changed, 545 insertions(+) create mode 100644 Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt create mode 100644 Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp create mode 100644 Tangential_complex/benchmark/Tangential_complex/StdAfx.h create mode 100644 Tangential_complex/benchmark/Tangential_complex/XML_exporter.h create mode 100644 Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp diff --git a/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt new file mode 100644 index 00000000000..7155f246c2b --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt @@ -0,0 +1,77 @@ +# Created by the script cgal_create_cmake_script +# This is the CMake script for compiling a CGAL application. + + +project( Tangential_complex_benchmark ) + +cmake_minimum_required(VERSION 2.6.2) +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) + if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) + cmake_policy(VERSION 2.8.4) + else() + cmake_policy(VERSION 2.6) + endif() +endif() + +# Creates a new CMake option, turned ON by default +option(ACTIVATE_MSVC_PRECOMPILED_HEADERS + "Activate precompiled headers in MSVC" + OFF) + +# Macro to add precompiled headers for MSVC +# This function does two things: +# 1. Enable precompiled headers on each file which is listed in "SourcesVar". +# 2. Add the content of "PrecompiledSource" (e.g. "StdAfx.cpp") to "SourcesVar". +MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar) + IF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS) + GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE) + SET(Sources ${${SourcesVar}}) + + SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource} + PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\"") + SET_SOURCE_FILES_PROPERTIES(${Sources} + PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeaders}\" /FI\"${PrecompiledHeader}\"") + # Add precompiled header to SourcesVar + LIST(APPEND ${SourcesVar} ${PrecompiledSource}) + ENDIF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS) +ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER) + +# The compiler might need more memory because of precompiled headers +if(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS AND NOT(MSVC_VERSION LESS 1310)) + set(CGAL_C_FLAGS "${CGAL_C_FLAGS} /Zm1000") + set(CGAL_CXX_FLAGS "${CGAL_CXX_FLAGS} /Zm1000") +endif() + +find_package(CGAL QUIET COMPONENTS Core ) + +if ( CGAL_FOUND ) + include( ${CGAL_USE_FILE} ) + + find_package( TBB QUIET ) + + if( TBB_FOUND ) + include(${TBB_USE_FILE}) + list(APPEND CGAL_3RD_PARTY_LIBRARIES ${TBB_LIBRARIES}) + endif() + + + include( CGAL_CreateSingleSourceCGALProgram ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + include_directories (BEFORE "../../include") + include_directories (BEFORE "include") + + set (SOURCE_FILES "benchmark_tc.cpp") + ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES) + create_single_source_cgal_program( ${SOURCE_FILES} ) + + else() + message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") + endif() + +else() + message(STATUS "This program requires the CGAL library, and will not be compiled.") +endif() + diff --git a/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp b/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp new file mode 100644 index 00000000000..15668dcadef --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp @@ -0,0 +1,2 @@ +// Build the precompiled headers. +#include "StdAfx.h" \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/StdAfx.h b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h new file mode 100644 index 00000000000..df71d9a8260 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h @@ -0,0 +1,14 @@ +#ifndef STDAFX_H +#define STDAFX_H + +// CGAL +#include +#include +//#include +//#include +//#include +//#include +//#include +#include + +#endif //STDAFX_H \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/XML_exporter.h b/Tangential_complex/benchmark/Tangential_complex/XML_exporter.h new file mode 100644 index 00000000000..158d3d648d4 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/XML_exporter.h @@ -0,0 +1,236 @@ +// Copyright (c) 2012 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin +// + +#include +#include +#include +#include +#include + +template +class Simple_XML_exporter +{ +public: + typedef value_type Value_type; + typedef std::vector Element; + typedef std::map Element_with_map; + typedef std::vector List_of_elements; + + Simple_XML_exporter( + const std::string &list_name, + const std::string &element_name, + const std::vector &subelement_names, + bool add_timestamp = true) + : m_list_name(list_name), + m_element_name(element_name), + m_subelement_names(subelement_names), + m_add_timestamp(add_timestamp) + {} + + bool add_element(const Element &element) + { + if (element.size() == m_subelement_names.size()) + { + m_list_of_elements.push_back(element); + return true; + } + else + { + std::cerr << "ERROR: element.size() == m_subelement_names.size()" << std::endl; + return false; + } + } + + bool add_element(Element_with_map &element) + { + Element elt; + + std::vector::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::const_iterator + it_subelement_name_end = m_subelement_names.end(); + for ( ; it_subelement_name != it_subelement_name_end ; ++it_subelement_name) + { + elt.push_back(element[*it_subelement_name]); + } + + return add_element(elt); + } + + bool export_to_xml(const std::string &filename) const + { + std::ofstream xmlfile; + xmlfile.open(filename.c_str()); + xmlfile << "" << std::endl; + xmlfile << "<" << m_list_name << ">" << std::endl; + + typename List_of_elements::const_iterator it_element = m_list_of_elements.begin(); + typename List_of_elements::const_iterator it_element_end = m_list_of_elements.end(); + for (int id = 1 ; it_element != it_element_end ; ++it_element, ++id) + { + xmlfile << " <" << m_element_name << ">" << std::endl; + std::vector::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::const_iterator + it_subelement_name_end = m_subelement_names.end(); + + if (m_add_timestamp) + xmlfile << " " << time(NULL) << " " << std::endl; + + for (int i = 0 ; + it_subelement_name != it_subelement_name_end ; + ++it_subelement_name, ++i) + { + xmlfile + << " <" << *it_subelement_name << "> " + << (*it_element)[i] + << " " << std::endl; + } + xmlfile << " " << std::endl; + } + + xmlfile << "" << std::endl; + xmlfile.close(); + return 0; + + } + +protected: + std::string m_list_name; + std::string m_element_name; + std::vector m_subelement_names; + List_of_elements m_list_of_elements; + bool m_add_timestamp; +}; + + + + + +template +class Streaming_XML_exporter +{ +public: + typedef value_type Value_type; + typedef std::vector Element; + typedef std::map Element_with_map; + typedef std::vector List_of_elements; + + Streaming_XML_exporter( + const std::string &filename, + const std::string &list_name, + const std::string &element_name, + const std::vector &subelement_names, + bool add_timestamp = true) + : m_list_name(list_name), + m_element_name(element_name), + m_subelement_names(subelement_names), + m_add_timestamp(add_timestamp) + { + m_xml_fstream.open(filename.c_str()); + if (m_xml_fstream.good()) + { + m_xml_fstream << "" << std::endl; + m_xml_fstream << "<" << m_list_name << ">" << std::endl; + } + else + { + std::cerr << "Could not open file '" << filename << "'." << std::endl; + } + } + + virtual ~Streaming_XML_exporter() + { + close_file(); + } + + void close_file() + { + m_xml_fstream.close(); + } + + bool add_element(const Element &element) + { + if (element.size() == m_subelement_names.size()) + { + m_xml_fstream << " <" << m_element_name << ">" << std::endl; + std::vector::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::const_iterator + it_subelement_name_end = m_subelement_names.end(); + + if (m_add_timestamp) + { + m_xml_fstream << " " << time(NULL) << " " << std::endl; + } + + for (int i = 0 ; + it_subelement_name != it_subelement_name_end ; + ++it_subelement_name, ++i) + { + m_xml_fstream + << " <" << *it_subelement_name << "> " + << element[i] + << " " << std::endl; + } + m_xml_fstream << " " << std::endl; + + // Save current pointer position + std::ofstream::streampos pos = m_xml_fstream.tellp(); + // Close the XML file (temporarily) so that the XML file is always correct + m_xml_fstream << "" << std::endl; + // Restore the pointer position so that the next "add_element" will overwrite + // the end of the file + m_xml_fstream.seekp(pos); + + m_xml_fstream.flush(); + return true; + } + else + { + std::cerr << "ERROR: element.size() == m_subelement_names.size()" << std::endl; + return false; + } + } + + bool add_element(Element_with_map &element) + { + Element elt; + + std::vector::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::const_iterator + it_subelement_name_end = m_subelement_names.end(); + for ( ; it_subelement_name != it_subelement_name_end ; ++it_subelement_name) + { + elt.push_back(element[*it_subelement_name]); + } + + return add_element(elt); + } + +protected: + std::ofstream m_xml_fstream; + std::string m_list_name; + std::string m_element_name; + std::vector m_subelement_names; + bool m_add_timestamp; +}; diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp new file mode 100644 index 00000000000..391d5162155 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -0,0 +1,216 @@ +#include +#include +#include +#include + +#include "../../test/Tangential_complex/test_utilities.h" + + +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif +#include "XML_exporter.h" +#define CGAL_TC_EXPORT_PERFORMANCE_DATA +#define CGAL_TC_SET_PERFORMANCE_DATA(value_name, value) \ + XML_perf_data::set(value_name, value); + +class XML_perf_data +{ +public: + typedef Streaming_XML_exporter XML_exporter; + + XML_perf_data(const std::string &filename) + : m_xml(filename, "ContainerPerformance", "Perf", + construct_subelements_names()) + {} + + virtual ~XML_perf_data() + { + } + + static XML_perf_data &get() + { + static XML_perf_data singleton(build_filename()); + return singleton; + } + + template + static void set(const std::string &name, Value_type value) + { + get().set_data(name, value); + } + + static void commit() + { + get().commit_current_element(); + } + +protected: + static std::string build_filename() + { + std::stringstream sstr; + sstr << "Performance_log_" << time(0) << ".xml"; + return sstr.str(); + } + + static std::vector construct_subelements_names() + { + std::vector subelements; + subelements.push_back("Name"); + subelements.push_back("Intrinsic_dim"); + subelements.push_back("Ambient_dim"); + subelements.push_back("Num_points"); + subelements.push_back("Noise"); + subelements.push_back("Init_time"); + subelements.push_back("Comput_time"); + subelements.push_back("Fix_time"); + + return subelements; + } + + void set_data(const std::string &name, const std::string &value) + { + m_current_element[name] = value; + } + + template + void set_data(const std::string &name, Value_type value) + { + std::stringstream sstr; + sstr << value; + set_data(name, sstr.str()); + } + + void commit_current_element() + { + m_xml.add_element(m_current_element); + m_current_element.clear(); + } + + XML_exporter m_xml; + XML_exporter::Element_with_map m_current_element; +}; + +#ifdef _DEBUG + const int NUM_POINTS = 50; +#else + const int NUM_POINTS = 30000; +#endif + +int main() +{ +#ifdef CGAL_LINKED_WITH_TBB +# ifdef _DEBUG + tbb::task_scheduler_init init(1); +# else + tbb::task_scheduler_init init(10); +# endif +#endif + + const int INTRINSIC_DIMENSION = 2; + const int AMBIENT_DIMENSION = 4; + + typedef CGAL::Epick_d > Kernel; + typedef Kernel::FT FT; + typedef Kernel::Point_d Point; + + int i = 0; + bool stop = false; + //for ( ; !stop ; ++i) + { + Kernel k; + 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 points; + //load_points_from_file( + // "data/points_10_10k.cin", std::back_inserter(points)/*, 600*/); + + std::vector points = + //generate_points_on_circle_2(NUM_POINTS, 3.); + //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); + //generate_points_on_plane(NUM_POINTS); + //generate_points_on_sphere_3(NUM_POINTS, 3.0); + //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + + + CGAL_TC_SET_PERFORMANCE_DATA("Name", "Klein bottle 4D"); + CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", INTRINSIC_DIMENSION); + CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", AMBIENT_DIMENSION); + CGAL_TC_SET_PERFORMANCE_DATA("Noise", 0.01); + +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set generated in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif + + std::cerr << "Number of points before sparsification: " + << points.size() << std::endl; + //points = sparsify_point_set( + // k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + std::cerr << "Number of points after sparsification: " + << points.size() << std::endl; + + CGAL::Tangential_complex< + Kernel, + INTRINSIC_DIMENSION, + CGAL::Parallel_tag> tc(points.begin(), points.end(), k); + double init_time = t.elapsed(); t.reset(); + + //tc.estimate_intrinsic_dimension(); + tc.compute_tangential_complex(); + double computation_time = t.elapsed(); t.reset(); + + std::set > incorrect_simplices; + //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + + t.reset(); + tc.fix_inconsistencies(); + double fix_time = t.elapsed(); t.reset(); + + double export_time = -1.; + if (INTRINSIC_DIMENSION <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + double export_time = t.elapsed(); t.reset(); + } + /*else + tc.number_of_inconsistent_simplices();*/ + + + std::cerr << std::endl + << "================================================" << std::endl + << "Number of vertices: " << tc.number_of_vertices() << std::endl + << "Computation times (seconds): " << std::endl + << " * Tangential complex: " << init_time + computation_time + << std::endl + << " - Init + kd-tree = " << init_time << std::endl + << " - TC computation = " << computation_time << std::endl + << " * Fix inconsistencies: " << fix_time << std::endl + << " * Export to OFF: " << export_time << std::endl + << "================================================" << std::endl + << std::endl; + + CGAL_TC_SET_PERFORMANCE_DATA("Num_points", tc.number_of_vertices()); + CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); + CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_time", fix_time); + } + + return 0; +} From dfbf8877514edba2cd53eaf6f54725072af69a88 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 20:29:19 +0100 Subject: [PATCH 157/487] Add TBB_USE_THREADING_TOOL in debug mode --- .../include/CGAL/Tangential_complex/config.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index ba34aaf568e..0715205be72 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -23,6 +23,14 @@ #include +// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false +// positives in Intel TBB +// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/) +#ifdef _DEBUG +# define TBB_USE_THREADING_TOOL +#endif + + //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE From 248c4b915da5c63fcfe83fc2b98bbfa60c709634 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 20:46:30 +0100 Subject: [PATCH 158/487] Comment mutexes out since we don't use them for now --- Tangential_complex/include/CGAL/Tangential_complex.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 51dc9a41639..abdca05b836 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -58,7 +58,7 @@ const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; #ifdef CGAL_LINKED_WITH_TBB # include -# include +//# include #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) @@ -165,7 +165,7 @@ class Tangential_complex #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - typedef tbb::queuing_mutex Tr_mutex; + //typedef tbb::queuing_mutex Tr_mutex; #endif #ifdef CGAL_TC_EXPORT_NORMALS typedef typename std::vector Normals; @@ -201,7 +201,7 @@ public: // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); #ifdef CGAL_LINKED_WITH_TBB - m_tr_mutexes.resize(m_points.size()); + //m_tr_mutexes.resize(m_points.size()); #endif m_tangent_spaces.resize(m_points.size()); m_weights.resize(m_points.size(), FT(0)); @@ -1102,7 +1102,7 @@ private: std::size_t tr_index) { #ifdef CGAL_LINKED_WITH_TBB - Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); + //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif Triangulation const& tr = m_triangulations[tr_index].tr(); @@ -1400,7 +1400,7 @@ private: Tr_container m_triangulations; // Contains the triangulations // and their center vertex #ifdef CGAL_LINKED_WITH_TBB - std::vector m_tr_mutexes; + //std::vector m_tr_mutexes; #endif #ifdef CGAL_TC_EXPORT_NORMALS Normals m_normals; From 785ac9690ce2be5b475494526219d32dbe2f5374 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 21:58:06 +0100 Subject: [PATCH 159/487] Update PCH --- .../benchmark/Tangential_complex/StdAfx.h | 10 +++++----- Tangential_complex/test/Tangential_complex/StdAfx.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/StdAfx.h b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h index df71d9a8260..573345d0022 100644 --- a/Tangential_complex/benchmark/Tangential_complex/StdAfx.h +++ b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h @@ -4,11 +4,11 @@ // CGAL #include #include -//#include -//#include -//#include -//#include -//#include +#include +#include +#include +#include +#include #include #endif //STDAFX_H \ No newline at end of file diff --git a/Tangential_complex/test/Tangential_complex/StdAfx.h b/Tangential_complex/test/Tangential_complex/StdAfx.h index 221d2a763cd..573345d0022 100644 --- a/Tangential_complex/test/Tangential_complex/StdAfx.h +++ b/Tangential_complex/test/Tangential_complex/StdAfx.h @@ -2,6 +2,7 @@ #define STDAFX_H // CGAL +#include #include #include #include From 035f87a65f6a606645e75a5b2caf0da274041790 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 21:58:34 +0100 Subject: [PATCH 160/487] Minor optimizations + comments --- Triangulation/include/CGAL/Triangulation_data_structure.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index bdbc16e7ad0..76c1ff84445 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -713,7 +713,9 @@ Triangulation_data_structure } } } - clear_visited_marks(start); + clear_visited_marks(start); // CJTODO: couldn't we use what is in "out" + // to make ot faster? (would require to + // replace the output iterator by a container) return ft; } @@ -999,7 +1001,7 @@ Triangulation_data_structure associate_vertex_with_full_cell(new_s, facet_index, v); set_neighbors(new_s, facet_index, - neighbor(old_s, facet_index), + outside_neighbor, mirror_index(old_s, facet_index)); // add the new full_cell to the list of new full_cells From 7bcf0e6e3bfb3c98df1301d4fe76ebc836bd3cd7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 22:00:26 +0100 Subject: [PATCH 161/487] Add sparsification to the benchmark --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 391d5162155..ad910233802 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -156,8 +156,8 @@ int main() std::cerr << "Number of points before sparsification: " << points.size() << std::endl; - //points = sparsify_point_set( - // k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + points = sparsify_point_set( + k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); std::cerr << "Number of points after sparsification: " << points.size() << std::endl; From 786f40d3769b66229268088d78d78ebf62c46e77 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 19 Dec 2014 07:16:31 +0100 Subject: [PATCH 162/487] "fix_inconsistencies" now returns the number of steps it took --- Tangential_complex/include/CGAL/Tangential_complex.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index abdca05b836..c5259f7eb8c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -318,7 +318,7 @@ public: #endif } - void fix_inconsistencies() + unsigned int fix_inconsistencies() { typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); typename Kernel::Construct_weighted_point_d cwp = @@ -341,10 +341,11 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Nothing to fix." << std::endl; #endif - return; + return 0; } bool done = false; + unsigned int num_steps = 0; while (!done) { // CJTODO: the parallel version is not working for now @@ -395,7 +396,10 @@ public: #endif done = (stats_after.second == 0); stats_before = stats_after; + ++num_steps; } + + return num_steps; } From 1885d666c751c7a1b48b51056691f90d0fbe3708 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 19 Dec 2014 12:04:56 +0100 Subject: [PATCH 163/487] Added new refresh strategy + better benchmark --- .../Tangential_complex/benchmark_tc.cpp | 33 ++++++++++++++----- .../include/CGAL/Tangential_complex.h | 12 +++++-- .../include/CGAL/Tangential_complex/config.h | 8 ++++- .../test/Tangential_complex/test_utilities.h | 10 +++--- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ad910233802..26606958ab2 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -52,7 +52,7 @@ protected: static std::string build_filename() { std::stringstream sstr; - sstr << "Performance_log_" << time(0) << ".xml"; + sstr << "perf_logs/Performance_log_" << time(0) << ".xml"; return sstr.str(); } @@ -64,9 +64,11 @@ protected: subelements.push_back("Ambient_dim"); subelements.push_back("Num_points"); subelements.push_back("Noise"); + subelements.push_back("Info"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); subelements.push_back("Fix_time"); + subelements.push_back("Fix_steps"); return subelements; } @@ -94,6 +96,7 @@ protected: XML_exporter::Element_with_map m_current_element; }; +const double NOISE = 0.01; #ifdef _DEBUG const int NUM_POINTS = 50; #else @@ -117,9 +120,11 @@ int main() typedef Kernel::FT FT; typedef Kernel::Point_d Point; - int i = 0; bool stop = false; - //for ( ; !stop ; ++i) + //for (int i = 0, NUM_POINTS = 10000 ; + // NUM_POINTS <= 50000 && !stop ; + // ++i, NUM_POINTS += (i%3 == 0 ? 5000 : 0)) + for (int i = 0 ; i < 5 && !stop ; ++i) { Kernel k; Wall_clock_timer t; @@ -140,14 +145,22 @@ int main() //generate_points_on_sphere_3(NUM_POINTS, 3.0); //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3., NOISE); //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); CGAL_TC_SET_PERFORMANCE_DATA("Name", "Klein bottle 4D"); CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", INTRINSIC_DIMENSION); CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", AMBIENT_DIMENSION); - CGAL_TC_SET_PERFORMANCE_DATA("Noise", 0.01); + CGAL_TC_SET_PERFORMANCE_DATA("Noise", NOISE); + XML_perf_data::set("Info", "" +#ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS + "ONLY_CHANGE_SIMPLEX_WEIGHTS " +#endif +#ifdef CGAL_TC_GLOBAL_REFRESH + "GLOBAL_REFRESH " +#endif + ); #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated in " << t_gen.elapsed() @@ -175,7 +188,7 @@ int main() //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); t.reset(); - tc.fix_inconsistencies(); + unsigned int num_fix_steps = tc.fix_inconsistencies(); double fix_time = t.elapsed(); t.reset(); double export_time = -1.; @@ -197,11 +210,11 @@ int main() << "================================================" << std::endl << "Number of vertices: " << tc.number_of_vertices() << std::endl << "Computation times (seconds): " << std::endl - << " * Tangential complex: " << init_time + computation_time - << std::endl + << " * Tangential complex: " << init_time + computation_time < stats_after = number_of_inconsistent_simplices(false); @@ -1141,8 +1145,10 @@ private: { m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); } - + +#if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); +#endif // We will try the other cells next time (incident_cells is not // valid anymore here) @@ -1212,8 +1218,10 @@ private: { m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); } - + +#if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); +#endif // We will try the other cells next time (incident_cells is not // valid anymore here) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 0715205be72..87e009191b7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -45,9 +45,15 @@ const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN //#define CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER +#define CGAL_TC_GLOBAL_REFRESH +//#define CGAL_TC_ON_DEMAND_REFRESH // CJTODO: not implemented yet + // The idea is to perform a global refresh + some local refreshes, just + // for local tri where there are some inconsistencies + // But be careful: refreshing the TC may invalidate cells, so the + // incident cells have to be recomputed again //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; -const double INPUT_SPARSITY = 0.1; +const double INPUT_SPARSITY = 0.05; #endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 9ada2a42ce9..95a4a9d20e7 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -357,7 +357,7 @@ std::vector generate_points_on_klein_bottle_3D( // a = big radius, b = small radius template std::vector generate_points_on_klein_bottle_4D( - std::size_t num_points, double a, double b, bool uniform = false) + std::size_t num_points, double a, double b, double noise = 0., bool uniform = false) { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; @@ -389,10 +389,10 @@ std::vector generate_points_on_klein_bottle_4D( } 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)*/) ); + (a + b*cos(v))*cos(u) + (noise == 0. ? 0. : rng.get_double(0, noise)), + (a + b*cos(v))*sin(u) + (noise == 0. ? 0. : rng.get_double(0, noise)), + b*sin(v)*cos(u/2) + (noise == 0. ? 0. : rng.get_double(0, noise)), + b*sin(v)*sin(u/2) + (noise == 0. ? 0. : rng.get_double(0, noise)))); #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) ++i; From e301781a26c3abde8c9b38aee13d6f2366c5a9c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 2 Jan 2015 17:35:36 +0100 Subject: [PATCH 164/487] Fixed TDS's incident_faces() using the wrong index for the first vertex (and added consts) (cherry picked from commit e312d7ddae0188ed0d99b4247f73871a57124f41) --- Triangulation/include/CGAL/Triangulation.h | 2 +- .../include/CGAL/Triangulation_data_structure.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index db57b817ddc..2dee695b77a 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -567,7 +567,7 @@ public: } template< typename OutputIterator > - OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) + OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) const { return tds().incident_faces(v, d, out); } diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 76c1ff84445..94818cc4627 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -624,10 +624,10 @@ public: return incident_faces(v, dim, out, std::less(), true); } template< typename OutputIterator, typename Comparator > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); + OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false) const; template< typename OutputIterator > OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, - std::less = std::less(), bool = false); + std::less = std::less(), bool = false) const; #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INPUT / OUTPUT @@ -725,7 +725,7 @@ template< typename OutputIterator > OutputIterator Triangulation_data_structure ::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, - std::less cmp, bool upper_faces) + std::less cmp, bool upper_faces) const { return incident_faces >(v, dim, out, cmp, upper_faces); } @@ -735,7 +735,7 @@ template< class Dim, class Vb, class Fcb > template< typename OutputIterator, typename Comparator > OutputIterator Triangulation_data_structure -::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp, bool upper_faces) +::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp, bool upper_faces) const { CGAL_precondition( 0 < dim ); if( dim >= current_dimension() ) @@ -789,13 +789,13 @@ Triangulation_data_structure // init state for enumerating all candidate faces: internal::Combination_enumerator f_idx(dim, v_idx + 1, current_dimension()); Face f(*s); - f.set_index(0, v_idx); + f.set_index(0, sorted_idx[v_idx]); while( ! f_idx.end() ) { - // check if face has already been found for( int i = 0; i < dim; ++i ) f.set_index(1 + i, sorted_idx[f_idx[i]]); - face_set.insert(f); + face_set.insert(f); // checks if face has already been found + // compute next sorted face (lexicographic enumeration) ++f_idx; } From 7a11937b970d5aa99a5e2aaa9b82c0ffd83fa40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 2 Jan 2015 17:35:36 +0100 Subject: [PATCH 165/487] Fixed TDS's incident_faces() using the wrong index for the first vertex (and added consts) (cherry picked from commit e312d7ddae0188ed0d99b4247f73871a57124f41) --- Triangulation/include/CGAL/Triangulation.h | 2 +- .../include/CGAL/Triangulation_data_structure.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index db57b817ddc..2dee695b77a 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -567,7 +567,7 @@ public: } template< typename OutputIterator > - OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) + OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) const { return tds().incident_faces(v, d, out); } diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index bdbc16e7ad0..f6097292c13 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -624,10 +624,10 @@ public: return incident_faces(v, dim, out, std::less(), true); } template< typename OutputIterator, typename Comparator > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); + OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false) const; template< typename OutputIterator > OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, - std::less = std::less(), bool = false); + std::less = std::less(), bool = false) const; #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INPUT / OUTPUT @@ -723,7 +723,7 @@ template< typename OutputIterator > OutputIterator Triangulation_data_structure ::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, - std::less cmp, bool upper_faces) + std::less cmp, bool upper_faces) const { return incident_faces >(v, dim, out, cmp, upper_faces); } @@ -733,7 +733,7 @@ template< class Dim, class Vb, class Fcb > template< typename OutputIterator, typename Comparator > OutputIterator Triangulation_data_structure -::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp, bool upper_faces) +::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp, bool upper_faces) const { CGAL_precondition( 0 < dim ); if( dim >= current_dimension() ) @@ -787,13 +787,13 @@ Triangulation_data_structure // init state for enumerating all candidate faces: internal::Combination_enumerator f_idx(dim, v_idx + 1, current_dimension()); Face f(*s); - f.set_index(0, v_idx); + f.set_index(0, sorted_idx[v_idx]); while( ! f_idx.end() ) { - // check if face has already been found for( int i = 0; i < dim; ++i ) f.set_index(1 + i, sorted_idx[f_idx[i]]); - face_set.insert(f); + face_set.insert(f); // checks if face has already been found + // compute next sorted face (lexicographic enumeration) ++f_idx; } From 43d81bb12beae260c4a408273563168cb2427a80 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 9 Jan 2015 15:02:46 +0100 Subject: [PATCH 166/487] Missing param --- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 39a4898ab5d..9d8853629c8 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -298,7 +298,7 @@ public: const Vertex_handle hint) { CGAL_assertion( Vertex_handle() != hint ); - return insert_if_in_star(p, hint->full_cell()); + return insert_if_in_star(p, star_center, hint->full_cell()); } // - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES From bb654aec952f98e71a47cd9221fd06e9f0d3c02f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 08:49:47 +0100 Subject: [PATCH 167/487] Fix the FIXMEs: "infinite vertex is NOT at index 0 a priori" --- Triangulation/include/CGAL/Regular_triangulation.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 9d8853629c8..0a44a9fce9d 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -798,8 +798,9 @@ Regular_triangulation reset_flat_orientation(); if( 1 <= current_dimension() ) { - // FIXME: infinite vertex is NOT at index 0 a priori. - Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); Orientation o = orientation(s); CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) @@ -857,8 +858,9 @@ Regular_triangulation v->set_point(p); if( current_dimension() >= 1 ) { - // FIXME: infinite vertex is NOT at index 0 a priori. - Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); Orientation o = orientation(s); CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) From 0b33b86e99a10818b1a4d4ebb69e00b1a7511498 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 08:49:47 +0100 Subject: [PATCH 168/487] Fix the FIXMEs: "infinite vertex is NOT at index 0 a priori" (cherry picked from commit bb654aec952f98e71a47cd9221fd06e9f0d3c02f) --- Triangulation/include/CGAL/Regular_triangulation.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 2755add7ab1..9b84a1d80d1 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -799,8 +799,9 @@ Regular_triangulation reset_flat_orientation(); if( 1 <= current_dimension() ) { - // FIXME: infinite vertex is NOT at index 0 a priori. - Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); Orientation o = orientation(s); CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) @@ -858,8 +859,9 @@ Regular_triangulation v->set_point(p); if( current_dimension() >= 1 ) { - // FIXME: infinite vertex is NOT at index 0 a priori. - Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); Orientation o = orientation(s); CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) From 10f7b688eb8886bb4d5fbadc42fa250232d19fb9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 11:10:33 +0100 Subject: [PATCH 169/487] Add output_weighted_point --- .../CGAL/IO/Triangulation_off_ostream.h | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 590c2a6b0e6..952adb6799d 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -46,6 +46,26 @@ output_point(std::ostream & os, const Traits &traits, const P & p) } } +// TODO: test if the stream is binary or text? +template +void +output_weighted_point(std::ostream & os, const Traits &traits, const P & p, + bool output_weight = true) +{ + typedef typename Traits::Compute_coordinate_d Ccd; + typename Traits::Point_drop_weight_d drop_w = + traits.point_drop_weight_d_object(); + typename Traits::Point_weight_d pt_weight = traits.point_weight_d_object(); + const Ccd ccd = traits.compute_coordinate_d_object(); + const int dim = traits.point_dimension_d_object()(p); + if (dim > 0) + { + output_point(os, traits, p); + if (output_weight) + os << " " << pt_weight(p); + } +} + // TODO: test if the stream is binary or text? /*template void From af405ac7a667368d70a00f3d669c473c5ccefb7c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 14:51:21 +0100 Subject: [PATCH 170/487] Add output_full_cell --- .../CGAL/IO/Triangulation_off_ostream.h | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 952adb6799d..2e09b9431e2 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -32,7 +32,7 @@ namespace Triangulation_IO { // TODO: test if the stream is binary or text? template -void +int output_point(std::ostream & os, const Traits &traits, const P & p) { typedef typename Traits::Compute_coordinate_d Ccd; @@ -44,11 +44,12 @@ output_point(std::ostream & os, const Traits &traits, const P & p) for (int i = 1 ; i < dim ; ++i) os << " " << CGAL::to_double(ccd(p, i)); } + return dim; } // TODO: test if the stream is binary or text? template -void +int output_weighted_point(std::ostream & os, const Traits &traits, const P & p, bool output_weight = true) { @@ -64,6 +65,26 @@ output_weighted_point(std::ostream & os, const Traits &traits, const P & p, if (output_weight) os << " " << pt_weight(p); } + return dim; +} + +// TODO: test if the stream is binary or text? +template +void +output_full_cell(std::ostream & os, const Traits &traits, const FCH & fch, + bool output_weights = false) +{ + typename FCH::value_type::Vertex_handle_iterator vit = fch->vertices_begin(); + for( ; vit != fch->vertices_end(); ++vit ) + { + int dim; + if (output_weights) + dim = output_weighted_point(os, traits, (*vit)->point()); + else + dim = output_point(os, traits, (*vit)->point()); + if (dim > 0) + os << std::endl; + } } // TODO: test if the stream is binary or text? From f320bdee4350abb0df9dced7d65865bbaf8b9412 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 14:56:03 +0100 Subject: [PATCH 171/487] Temporary bug fix Do not insert a point when an already existing point in at the same place. TODO: something better when the weight is different. --- Triangulation/include/CGAL/Regular_triangulation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 0a44a9fce9d..dbf66a91380 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -823,7 +823,7 @@ Regular_triangulation case Base::ON_VERTEX: { Vertex_handle v = s->vertex(f.index(0)); - v->set_point(p); + //v->set_point(p); // CJTODO see T3.h l.3570 return v; break; } @@ -885,7 +885,7 @@ Regular_triangulation case Base::ON_VERTEX: { Vertex_handle v = s->vertex(f.index(0)); - v->set_point(p); + //v->set_point(p); // CJTODO see T3.h l.3570 return v; break; } From d775cde6e615e846e6c4c8d85b544ccf327020e1 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 17:47:09 +0100 Subject: [PATCH 172/487] Better bug fix Handles the case where an existing point is at the same place as the point we're trying to insert. --- .../include/CGAL/Regular_triangulation.h | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index dbf66a91380..6335cdbd3d5 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -823,9 +823,23 @@ Regular_triangulation case Base::ON_VERTEX: { Vertex_handle v = s->vertex(f.index(0)); - //v->set_point(p); // CJTODO see T3.h l.3570 - return v; - break; + typename RTTraits::Point_weight_d pw = + geom_traits().point_weight_d_object(); + + if (pw(p) == pw(v->point())) + return v; + // If dim == 0 and the new point has a bigger weight, + // we replace the point + else if (current_dimension() == 0) + { + if (pw(p) > pw(v->point())) + v->set_point(p); + else + return v; + } + // Otherwise, we apply the "normal" algorithm + + // !NO break here! } default: if( 1 == current_dimension() ) @@ -885,9 +899,22 @@ Regular_triangulation case Base::ON_VERTEX: { Vertex_handle v = s->vertex(f.index(0)); - //v->set_point(p); // CJTODO see T3.h l.3570 - return v; - break; + typename RTTraits::Point_weight_d pw = + geom_traits().point_weight_d_object(); + if (pw(p) == pw(v->point())) + return v; + // If dim == 0 and the new point has a bigger weight, + // we replace the point + else if (current_dimension() == 0) + { + if (pw(p) > pw(v->point())) + v->set_point(p); + else + return v; + } + // Otherwise, we apply the "normal" algorithm + + // !NO break here! } default: { From c32373e75bd0f0b56ea13da5db7aad2b8ef47a9b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 17:49:25 +0100 Subject: [PATCH 173/487] Rename variable to avoid confusion + remove useless initialization --- Triangulation/include/CGAL/Regular_triangulation.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 6335cdbd3d5..b6bcdc072b0 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -949,26 +949,26 @@ Regular_triangulation { typedef std::vector Full_cell_h_vector; - bool is_in_conflict = true; + bool in_conflict; if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( *this, p, coaffine_orientation_predicate(), power_test_in_flat_predicate()); - is_in_conflict = c(s); + in_conflict = c(s); } else { Orientation_d ori = geom_traits().orientation_d_object(); Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); - is_in_conflict = c(s); + in_conflict = c(s); } // If p is not in conflict with s, then p is hidden // => we don't insert it - if (!is_in_conflict) + if (!in_conflict) { m_hidden_points.push_back(p); return Vertex_handle(); From dfc8038579d976685cf4af20e8059dc9de7daaf0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 17:57:29 +0100 Subject: [PATCH 174/487] Add code to load points from a file (commented) --- .../test/Tangential_complex/test_tangential_complex.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 77102284fbd..ed25c17c1f1 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -55,6 +55,7 @@ int main() #ifdef CGAL_TC_PROFILING Wall_clock_timer t_gen; #endif + std::vector points = //generate_points_on_circle_2(NUM_POINTS, 3.); //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); @@ -64,7 +65,12 @@ int main() //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); - + + // LOAD FROM A FILE + //std::vector points; + //load_points_from_file( + // "data/points_10_10k.cin", std::back_inserter(points)); + #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated in " << t_gen.elapsed() << " seconds." << std::endl; From 614add44becd8412afe91c82c2f4e293cc80fa00 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 13 Jan 2015 15:27:21 +0100 Subject: [PATCH 175/487] Added a trace in verbose mode --- Tangential_complex/test/Tangential_complex/test_utilities.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 95a4a9d20e7..9ed98fa4c20 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -167,6 +167,10 @@ bool load_points_from_file( ++i; } +#ifdef CGAL_TC_VERBOSE + std::cerr << "'" << filename << "' loaded." << std::endl; +#endif + return true; } From a2423310b170e1a0f77f0bf0c20c9c3d2f39659d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 15 Jan 2015 15:39:25 +0100 Subject: [PATCH 176/487] Handles the case when the local triangulation has a dimension < intrinsic dim --- .../include/CGAL/Tangential_complex.h | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 1959d0270f2..0f007443c75 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -439,7 +439,7 @@ public: if (tr.is_infinite(*it_c)) // Don't check infinite cells continue; - if (!is_simplex_consistent(*it_c)) + if (!is_simplex_consistent(*it_c, tr.current_dimension())) ++num_inconsistent_simplices; ++num_simplices; } @@ -596,7 +596,7 @@ public: continue; } Indexed_simplex simplex; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) simplex.insert((*it_c)->vertex(i)->data()); stars_simplices.insert(simplex); @@ -1029,10 +1029,10 @@ private: } // A simplex here is a local tri's full cell handle - bool is_simplex_consistent(Tr_full_cell_handle fch) + bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) { std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < cur_dim + 1 ; ++i) { std::size_t data = fch->vertex(i)->data(); c.insert(data); @@ -1043,6 +1043,8 @@ private: // A simplex here is a list of point indices bool is_simplex_consistent(std::set const& simplex) { + int cur_dim_plus_1 = static_cast(simplex.size()); + // Check if the simplex is in the stars of all its vertices std::set::const_iterator it_point_idx = simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p @@ -1065,7 +1067,7 @@ private: for ( ; !found && it_c != it_c_end ; ++it_c) { std::set cell; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < cur_dim_plus_1 ; ++i) cell.insert((*it_c)->vertex(i)->data()); if (cell == simplex) found = true; @@ -1116,6 +1118,7 @@ private: Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); const Tr_traits &local_tr_traits = tr.geom_traits(); + int cur_dim = tr.current_dimension(); std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); @@ -1127,11 +1130,10 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { - #ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) { std::size_t data = (*it_c)->vertex(i)->data(); c.insert(data); @@ -1140,6 +1142,8 @@ private: // Inconsistent? if (!is_simplex_consistent(c)) { + //m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); + //break; // CJTODO TEMP CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) { @@ -1156,7 +1160,7 @@ private: } #else // Inconsistent? - if (!is_simplex_consistent(*it_c)) + if (!is_simplex_consistent(*it_c, cur_dim)) { // Get the k + 2 closest points @@ -1175,7 +1179,7 @@ private: Point global_center(center.begin(), center.end());*/ std::vector simplex_pts; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < cur_dim + 1 ; ++i) simplex_pts.push_back((*it_c)->vertex(i)->point()); //typename Tr_traits::Power_center_d power_center = From c4820faa1b0cd56092112df585d657d1de49c0da Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 15 Jan 2015 15:46:00 +0100 Subject: [PATCH 177/487] Restore original code --- .../include/CGAL/Tangential_complex/Point_cloud.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 1e466d65049..4c6c2904003 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -141,12 +141,9 @@ public: size_t *neighbor_indices, FT *squared_distance) const { - /*std::vector sp_vec( + std::vector sp_vec( m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), - m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));*/ // CJTODO remettre - std::vector sp_vec; - for (int i = 0 ; i < 4 ; ++i) - sp_vec.push_back(sp[i]); + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0)); nanoflann::KNNResultSet result_set(k); result_set.init(neighbor_indices, squared_distance); m_kd_tree.findNeighbors(result_set, @@ -167,12 +164,9 @@ public: std::vector > &neighbors, bool sort_output = true) { - /*std::vector sp_vec( + std::vector sp_vec( m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), - m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));*/ // CJTODO remettre - std::vector sp_vec; - for (int i = 0 ; i < 4 ; ++i) - sp_vec.push_back(sp[i]); + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0)); m_kd_tree.radiusSearch(&sp_vec[0], radius, neighbors, From dd869507608ecc7038206c10971beead4b8949c3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 16 Jan 2015 16:53:40 +0100 Subject: [PATCH 178/487] Improve code using a transform_iterator --- .../include/CGAL/Tangential_complex.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 0f007443c75..fc6e21699a7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -47,6 +47,7 @@ const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; #include #include +#include #include #include @@ -171,6 +172,12 @@ class Tangential_complex typedef typename std::vector Normals; #endif + // For transform_iterator + static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) + { + return vh->point(); + } + public: /// Constructor for a range of points @@ -833,13 +840,12 @@ private: } else { - std::vector cell_pts; - cell_pts.reserve(Intrinsic_dimension + 1); - // For each point p - for (int ii = 0 ; ii <= Intrinsic_dimension ; ++ii) - cell_pts.push_back(cell->vertex(ii)->point()); + Tr_point c = power_center( + boost::make_transform_iterator( + cell->vertices_begin(), vertex_handle_to_point), + boost::make_transform_iterator( + cell->vertices_end(), vertex_handle_to_point)); - Tr_point c = power_center(cell_pts.begin(), cell_pts.end()); FT sq_power_sphere_diam = 4*point_weight(c); if (!star_sphere_squared_radius From 751f592f44afbe354628793cb5ec8586e894af75 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 19 Jan 2015 15:52:03 +0100 Subject: [PATCH 179/487] Added an option to perturb point positions instead of weights --- .../include/CGAL/Tangential_complex.h | 131 ++++++++++++++---- .../include/CGAL/Tangential_complex/config.h | 4 + 2 files changed, 106 insertions(+), 29 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fc6e21699a7..b7e4f30960f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,7 +23,8 @@ #define TANGENTIAL_COMPLEX_H #include -const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; +const double HALF_SPARSITY = 0.5*INPUT_SPARSITY; +const double SQ_HALF_SPARSITY = HALF_SPARSITY*HALF_SPARSITY; #include #include @@ -36,6 +37,7 @@ const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; #include #include #include +#include #ifdef CGAL_TC_PROFILING # include @@ -114,6 +116,7 @@ class Tangential_complex typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; + typedef typename Tr_traits::Vector_d Tr_vector; typedef std::vector Tangent_space_basis; @@ -163,14 +166,12 @@ class Tangential_complex typedef typename std::vector TS_container; typedef typename std::vector Tr_container; + typedef typename std::vector Vectors; #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm //typedef tbb::queuing_mutex Tr_mutex; #endif -#ifdef CGAL_TC_EXPORT_NORMALS - typedef typename std::vector Normals; -#endif // For transform_iterator static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) @@ -186,7 +187,8 @@ public: const Kernel &k = Kernel()) : m_k(k), m_points(first, last), - m_points_ds(m_points) + m_points_ds(m_points), + m_ambiant_dim(k.point_dimension_d_object()(*first)) {} /// Destructor @@ -211,7 +213,12 @@ public: //m_tr_mutexes.resize(m_points.size()); #endif m_tangent_spaces.resize(m_points.size()); +#ifdef CGAL_TC_PERTURB_WEIGHT m_weights.resize(m_points.size(), FT(0)); +#endif +#ifdef CGAL_TC_PERTURB_POSITION + m_translations.resize(m_points.size()); +#endif #ifdef CGAL_TC_EXPORT_NORMALS m_normals.resize(m_points.size()); #endif @@ -240,13 +247,11 @@ public: void estimate_intrinsic_dimension() { - const int amb_dim = m_k.point_dimension_d_object()(*m_points.begin()); - // Kernel functors typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - std::vector sum_eigen_values(amb_dim, FT(0)); + std::vector sum_eigen_values(m_ambiant_dim, FT(0)); Points::const_iterator it_p = m_points.begin(); Points::const_iterator it_p_end = m_points.end(); @@ -261,13 +266,13 @@ public: //******************************* PCA ************************************* // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { - for (int i = 0 ; i < amb_dim ; ++i) + for (int i = 0 ; i < m_ambiant_dim ; ++i) mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); @@ -277,7 +282,7 @@ public: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = 0 ; i < amb_dim ; ++i) + for (int i = 0 ; i < m_ambiant_dim ; ++i) sum_eigen_values[i] += eig.eigenvalues()[i]; //************************************************************************* @@ -327,9 +332,8 @@ public: unsigned int fix_inconsistencies() { - typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); - typename Kernel::Construct_weighted_point_d cwp = - m_k.construct_weighted_point_d_object(); + typename Kernel::Point_drop_weight_d drop_w = + m_k.point_drop_weight_d_object(); #ifdef CGAL_TC_VERBOSE std::cerr << "Fixing inconsistencies..." << std::endl; @@ -741,6 +745,8 @@ private: m_k.difference_of_points_d_object(); typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); // Triangulation's traits functor & objects typename Tr_traits::Squared_distance_d sqdist = @@ -753,8 +759,13 @@ private: local_tr_traits.power_center_d_object();*/ // CJTODO typename Get_functor::type power_center(local_tr_traits); - // Estimate the tangent space +#ifdef CGAL_TC_PERTURB_POSITION + const Point center_pt = k_transl(m_points[i], m_translations[i]); +#else const Point ¢er_pt = m_points[i]; +#endif + + // Estimate the tangent space if (!tangent_spaces_are_already_computed) { #ifdef CGAL_TC_EXPORT_NORMALS @@ -772,7 +783,12 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(Intrinsic_dimension, ORIGIN), - m_weights[i]); +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[i] +#else + 0 +#endif + ); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -796,12 +812,21 @@ private: // ith point = p, which is already inserted if (neighbor_point_idx != i) { +#ifdef CGAL_TC_PERTURB_POSITION + const Point neighbor_pt = k_transl( + m_points[neighbor_point_idx], m_translations[neighbor_point_idx]); +#else const Point &neighbor_pt = m_points[neighbor_point_idx]; +#endif +#ifdef CGAL_TC_PERTURB_WEIGHT FT neighbor_weight = m_weights[neighbor_point_idx]; +#else + FT neighbor_weight = 0; +#endif if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + SQ_HALF_SPARSITY) + > *star_sphere_squared_radius + 4*SQ_HALF_SPARSITY) // CJTODO: why is "4*" needed? break; Tr_point proj_pt = project_point_and_compute_weight( @@ -815,7 +840,7 @@ private: // CJTODO TEMP TEST /*if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + SQ_HALF_SPARSITY) + > *star_sphere_squared_radius + 4*SQ_HALF_SPARSITY) std::cout << "ARGGGGGGGH" << std::endl;*/ vh->data() = neighbor_point_idx; @@ -897,15 +922,14 @@ private: //******************************* PCA ************************************* - const int amb_dim = m_k.point_dimension_d_object()(p); // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { - for (int i = 0 ; i < amb_dim ; ++i) + for (int i = 0 ; i < m_ambiant_dim ; ++i) mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); @@ -915,18 +939,20 @@ private: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = amb_dim - 1 ; i >= amb_dim - Intrinsic_dimension ; --i) + for (int i = m_ambiant_dim - 1 ; + i >= m_ambiant_dim - Intrinsic_dimension ; + --i) { ts.push_back(constr_vec( - amb_dim, + m_ambiant_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + amb_dim)); + eig.eigenvectors().col(i).data() + m_ambiant_dim)); } #ifdef CGAL_TC_EXPORT_NORMALS *p_normal = constr_vec( - amb_dim, - eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data(), - eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data() + amb_dim); + m_ambiant_dim, + eig.eigenvectors().col(m_ambiant_dim - Intrinsic_dimension - 1).data(), + eig.eigenvectors().col(m_ambiant_dim - Intrinsic_dimension - 1).data() + m_ambiant_dim); #endif //************************************************************************* @@ -1120,6 +1146,16 @@ private: #ifdef CGAL_LINKED_WITH_TBB //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif + +#ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator(m_ambiant_dim, 1); +# else + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator(Intrinsic_dimension, 1); +# endif +#endif Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); @@ -1193,11 +1229,21 @@ private: typename Get_functor::type power_center(local_tr_traits); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); + typename Tr_traits::Construct_weighted_point_d cwp = + local_tr_traits.construct_weighted_point_d_object(); + //typename Tr_traits::Point_to_vector_d pt_to_vec = + // local_tr_traits.construct_point_to_vector_d_object(); typename Kernel::Translated_point_d k_transl = m_k.translated_point_d_object(); typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); +#if defined(CGAL_TC_PERTURB_POSITION) && defined(CGAL_TC_PERTURB_POSITION_GLOBAL) + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); +#endif Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; @@ -1226,7 +1272,28 @@ private: it != neighbors.end() ; ++it) { +#ifdef CGAL_TC_PERTURB_WEIGHT m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); +#endif + +#ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + m_translations[*it] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + Tr_point local_random_transl = + cwp(*tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[*it]; + global_transl = k_constr_vec(m_ambiant_dim); + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +#endif } #if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -1263,7 +1330,7 @@ private: int num_coords = min(ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS - Normals::const_iterator it_n = m_normals.begin(); + Vectors::const_iterator it_n = m_normals.begin(); #endif typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -1413,9 +1480,15 @@ private: private: const Kernel m_k; + const int m_ambiant_dim; Points m_points; +#ifdef CGAL_TC_PERTURB_WEIGHT Weights m_weights; +#endif +#ifdef CGAL_TC_PERTURB_POSITION + Vectors m_translations; +#endif Points_ds m_points_ds; TS_container m_tangent_spaces; @@ -1425,7 +1498,7 @@ private: //std::vector m_tr_mutexes; #endif #ifdef CGAL_TC_EXPORT_NORMALS - Normals m_normals; + Vectors m_normals; #endif }; // /class Tangential_complex diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 87e009191b7..7e424afbb55 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -51,6 +51,10 @@ const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; // for local tri where there are some inconsistencies // But be careful: refreshing the TC may invalidate cells, so the // incident cells have to be recomputed again +#define CGAL_TC_PERTURB_POSITION +# define CGAL_TC_PERTURB_POSITION_TANGENTIAL // default +//# define CGAL_TC_PERTURB_POSITION_GLOBAL +//#define CGAL_TC_PERTURB_WEIGHT //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; From ef3c9f951d2b692d70b46811fed2662fca56f6ac Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 19 Jan 2015 15:53:07 +0100 Subject: [PATCH 180/487] Fix sparsify_point_set --- .../test/Tangential_complex/test_utilities.h | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 9ed98fa4c20..f953736efd7 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -105,6 +105,8 @@ sparsify_point_set( Points_ds points_ds(input_pts); + std::vector dropped_points(input_pts.size(), false); + // Parse the following points, and add them if they are not too close to // the other points std::size_t pt_idx = 0; @@ -112,6 +114,11 @@ sparsify_point_set( it_pt != input_pts.end(); ++it_pt, ++pt_idx) { + if (dropped_points[pt_idx]) + continue; + + output.push_back(*it_pt); + INS_range ins_range = points_ds.query_incremental_ANN(*it_pt); // Drop it if there is another point that: @@ -123,16 +130,11 @@ sparsify_point_set( { std::size_t neighbor_point_idx = nn_it->first; typename Kernel::FT sq_dist = nn_it->second; - // The neighbor is further, we keep the point - if (sq_dist >= min_squared_dist) - { - output.push_back(*it_pt); + // The neighbor is too close, we drop the neighbor + if (sq_dist < min_squared_dist) + dropped_points[neighbor_point_idx] = true; + else break; - } - // The neighbor is close and it has a higher index - else if (neighbor_point_idx > pt_idx) - break; // We drop the point - // Otherwise, we go the next closest point } } From 928d249c96dd9b06d45acf5a816967f03a0710bd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 19 Jan 2015 15:54:00 +0100 Subject: [PATCH 181/487] Improved test file --- .../test_tangential_complex.cpp | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index ed25c17c1f1..4acbb1a0843 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 10000; + const int NUM_POINTS = 30000; #endif int main() @@ -36,8 +36,8 @@ int main() # endif #endif - const int INTRINSIC_DIMENSION = 2; - const int AMBIENT_DIMENSION = 4; + const int INTRINSIC_DIMENSION = 3; + const int AMBIENT_DIMENSION = 9; typedef CGAL::Epick_d > Kernel; typedef Kernel::FT FT; @@ -56,7 +56,7 @@ int main() Wall_clock_timer t_gen; #endif - std::vector points = + /*std::vector points = //generate_points_on_circle_2(NUM_POINTS, 3.); //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); //generate_points_on_plane(NUM_POINTS); @@ -64,22 +64,23 @@ int main() //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); - //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.);*/ // LOAD FROM A FILE - //std::vector points; - //load_points_from_file( - // "data/points_10_10k.cin", std::back_inserter(points)); + std::vector points; + load_points_from_file( + "data/SO3_10000.txt", std::back_inserter(points)); #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated in " << t_gen.elapsed() << " seconds." << std::endl; #endif + std::size_t num_points_before = points.size(); points = sparsify_point_set( k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); - std::cerr << "Number of points after sparsification: " - << points.size() << std::endl; + std::cerr << "Number of points before/after sparsification: " + << num_points_before << " / " << points.size() << std::endl; CGAL::Tangential_complex< Kernel, @@ -89,24 +90,37 @@ int main() tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - + std::set > incorrect_simplices; //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + double export_before_time = -1.; + if (INTRINSIC_DIMENSION <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << "_BEFORE_FIX.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + export_before_time = t.elapsed(); t.reset(); + } + + t.reset(); tc.fix_inconsistencies(); double fix_time = t.elapsed(); t.reset(); - double export_time = -1.; + double export_after_time = -1.; if (INTRINSIC_DIMENSION <= 3) { t.reset(); std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION - << "_in_R" << AMBIENT_DIMENSION << ".off"; + output_filename << "output/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); - double export_time = t.elapsed(); t.reset(); + export_after_time = t.elapsed(); t.reset(); } /*else tc.number_of_inconsistent_simplices();*/ @@ -120,8 +134,9 @@ int main() << std::endl << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl + << " * Export to OFF (before fix): " << export_before_time << std::endl << " * Fix inconsistencies: " << fix_time << std::endl - << " * Export to OFF: " << export_time << std::endl + << " * Export to OFF (after fix): " << export_after_time << std::endl << "================================================" << std::endl << std::endl; } From cc1379396c2b7513beb05680a80b0c84d271461b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jan 2015 12:32:36 +0100 Subject: [PATCH 182/487] Improved output --- .../include/CGAL/Tangential_complex.h | 88 ++++++++++++++----- .../include/CGAL/Tangential_complex/config.h | 3 +- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b7e4f30960f..d8e70f08b2a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -339,26 +339,29 @@ public: std::cerr << "Fixing inconsistencies..." << std::endl; #endif +#ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES std::pair stats_before = number_of_inconsistent_simplices(false); -#ifdef CGAL_TC_VERBOSE +# ifdef CGAL_TC_VERBOSE std::cerr << "Initial number of inconsistencies: " << stats_before.second << std::endl; -#endif +# endif if (stats_before.second == 0) { -#ifdef CGAL_TC_VERBOSE +# ifdef CGAL_TC_VERBOSE std::cerr << "Nothing to fix." << std::endl; -#endif +# endif return 0; } +#endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES bool done = false; unsigned int num_steps = 0; while (!done) { + std::size_t num_inconsistent_local_tr = 0; // CJTODO: the parallel version is not working for now /*#ifdef CGAL_LINKED_WITH_TBB // Parallel @@ -373,45 +376,76 @@ public: else #endif // CGAL_LINKED_WITH_TBB*/ { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) - try_to_solve_inconsistencies_in_a_local_triangulation(i); + { + num_inconsistent_local_tr += + (try_to_solve_inconsistencies_in_a_local_triangulation(i) ? 1 : 0); + } +#ifdef CGAL_TC_PROFILING + std::cerr << "Attempt to fix inconsistencies: " << t.elapsed() + << " seconds." << std::endl; +#endif } #ifdef CGAL_TC_GLOBAL_REFRESH refresh_tangential_complex(); #endif +#ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES std::pair stats_after = number_of_inconsistent_simplices(false); -#ifdef CGAL_TC_VERBOSE std::cerr << std::endl - << "================================================" << std::endl - << "Inconsistencies:\n" + << "==========================================================" + << std::endl + << "Inconsistencies (detailed stats):\n" << " * Number of vertices: " << m_points.size() << std::endl << std::endl << " * BEFORE fix_inconsistencies:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_before.first << std::endl - << " - Number of inconsistent simplices in stars (incl. duplicates): " - << stats_before.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_before.second / stats_before.first << "%" + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_before.second + << " (" << 100. * stats_before.second / stats_before.first << "%)" + << std::endl + << " * Num inconsistent local triangulations: " + << num_inconsistent_local_tr + << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl << std::endl << " * AFTER fix_inconsistencies:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_after.first << std::endl - << " - Number of inconsistent simplices in stars (incl. duplicates): " + << " - Num inconsistent simplices in stars (incl. duplicates): " << stats_after.second << std::endl << " - Percentage of inconsistencies: " << 100. * stats_after.second / stats_before.first << "%" << std::endl - << "================================================" << std::endl; -#endif - done = (stats_after.second == 0); + << "==========================================================" + << std::endl; + stats_before = stats_after; + +#else // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES +# ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "==========================================================" + << std::endl + << "fix_inconsistencies():\n" + << " * " << m_points.size() << " vertices" << std::endl + << " * " << num_inconsistent_local_tr + << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" + << " inconsistent triangulations encountered" << std::endl + << "==========================================================" + << std::endl; +# endif +#endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES + ++num_steps; + done = (num_inconsistent_local_tr == 0); } return num_steps; @@ -459,7 +493,8 @@ public: if (verbose) { std::cerr << std::endl - << "================================================" << std::endl + << "==========================================================" + << std::endl << "Inconsistencies:\n" << " * Number of vertices: " << m_points.size() << std::endl << " * Total number of simplices in stars (incl. duplicates): " @@ -468,7 +503,8 @@ public: << num_inconsistent_simplices << std::endl << " * Percentage of inconsistencies: " << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl - << "================================================" << std::endl; + << "==========================================================" + << std::endl; } return std::make_pair(num_simplices, num_inconsistent_simplices); @@ -1140,9 +1176,11 @@ private: }; #endif // CGAL_LINKED_WITH_TBB - void try_to_solve_inconsistencies_in_a_local_triangulation( + bool try_to_solve_inconsistencies_in_a_local_triangulation( std::size_t tr_index) { + bool is_inconsistent = false; + #ifdef CGAL_LINKED_WITH_TBB //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif @@ -1184,6 +1222,8 @@ private: // Inconsistent? if (!is_simplex_consistent(c)) { + is_inconsistent = true; + //m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); //break; // CJTODO TEMP CGAL::Random rng; @@ -1204,6 +1244,8 @@ private: // Inconsistent? if (!is_simplex_consistent(*it_c, cur_dim)) { + is_inconsistent = true; + // Get the k + 2 closest points /*int point_dim = m_k.point_dimension_d_object()(*m_points.begin()); @@ -1307,6 +1349,8 @@ private: #endif } + + return is_inconsistent; } std::ostream &export_vertices_to_off( @@ -1461,7 +1505,8 @@ private: #ifdef CGAL_TC_VERBOSE std::cerr << std::endl - << "================================================" << std::endl + << "==========================================================" + << std::endl << "Export to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl << " * Total number of simplices in stars (incl. duplicates): " @@ -1472,7 +1517,8 @@ private: << (num_simplices > 0 ? 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" << std::endl - << "================================================" << std::endl; + << "==========================================================" + << std::endl; #endif return os; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 7e424afbb55..3b696b146fa 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -34,6 +34,7 @@ //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE +//#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES // Solving inconsistencies: only change the weights of the inconsistent simplex // or more? @@ -57,7 +58,7 @@ const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; //#define CGAL_TC_PERTURB_WEIGHT //========================= Parameters ======================================== -const std::size_t NUM_POINTS_FOR_PCA = 50; +const std::size_t NUM_POINTS_FOR_PCA = 30; const double INPUT_SPARSITY = 0.05; #endif // CGAL_TC_CONFIG_H From 9255141ae7fb47b8e48cce83291a1e70893e2ff8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jan 2015 12:34:37 +0100 Subject: [PATCH 183/487] Rename macro --- Tangential_complex/include/CGAL/Tangential_complex.h | 2 +- Tangential_complex/include/CGAL/Tangential_complex/config.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d8e70f08b2a..97d6005b825 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1210,7 +1210,7 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { -#ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS +#ifdef CGAL_TC_PERTURB_THE_SIMPLEX_ONLY std::set c; for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 3b696b146fa..2d5f4b6e96d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -36,9 +36,8 @@ #define CGAL_TC_VERBOSE //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -// Solving inconsistencies: only change the weights of the inconsistent simplex -// or more? -//#define CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS +// Solving inconsistencies: only perturb the inconsistent simplex or more? +//#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY // Otherwise... const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; From be21ff3dc1beab9cd260351d0d3ed9ece79ca1ef Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jan 2015 19:49:32 +0100 Subject: [PATCH 184/487] Added another strategy to perturb the points --- .../include/CGAL/Tangential_complex.h | 159 ++++++++++++++---- .../include/CGAL/Tangential_complex/config.h | 8 +- 2 files changed, 131 insertions(+), 36 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 97d6005b825..c916b61a2f1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1210,6 +1210,9 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { +//***************************************************************************** +// STRATEGY 1: perturb all the points of the first inconsistent simplex +//***************************************************************************** #ifdef CGAL_TC_PERTURB_THE_SIMPLEX_ONLY std::set c; @@ -1223,44 +1226,130 @@ private: if (!is_simplex_consistent(c)) { is_inconsistent = true; + +# ifdef CGAL_TC_PERTURB_POSITION + typename Tr_traits::Construct_weighted_point_d cwp = + local_tr_traits.construct_weighted_point_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); +# endif +# endif - //m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); - //break; // CJTODO TEMP CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) { +# ifdef CGAL_TC_PERTURB_WEIGHT m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); +# endif + +# ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + m_translations[*it] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + Tr_point local_random_transl = + cwp(*tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[*it]; + global_transl = k_constr_vec(m_ambiant_dim); + const Tangent_space_basis &tsb = m_tangent_spaces[*it]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +# endif } -#if !defined(CGAL_TC_GLOBAL_REFRESH) +# if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); -#endif +# endif // We will try the other cells next time (incident_cells is not // valid anymore here) break; } -#else + +//***************************************************************************** +// STRATEGY 2: perturb the center point only +//***************************************************************************** +#elif defined(CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY) + if (!is_simplex_consistent(*it_c, cur_dim)) + { + is_inconsistent = true; +# ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); +# endif + +# ifdef CGAL_TC_PERTURB_POSITION + typename Tr_traits::Construct_weighted_point_d cwp = + local_tr_traits.construct_weighted_point_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); + +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); + m_translations[tr_index] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + Tr_point local_random_transl = + cwp(*tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[tr_index]; + //Vector &global_transl = m_translations[ + // (*it_c)->vertex(rand()%tr.current_dimension())->data()]; + global_transl = k_constr_vec(m_ambiant_dim); + const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +# endif + +# if !defined(CGAL_TC_GLOBAL_REFRESH) + refresh_tangential_complex(); +# endif + + // We will try the other cells next time (incident_cells is not + // valid anymore here) + break; + } + +//***************************************************************************** +// STRATEGY 3: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS +// closest points (to the power center of first the inconsistent cell) +//***************************************************************************** +#else // Inconsistent? if (!is_simplex_consistent(*it_c, cur_dim)) { is_inconsistent = true; - // Get the k + 2 closest points - - /*int point_dim = m_k.point_dimension_d_object()(*m_points.begin()); - std::vector center(point_dim, FT(0)); - for (int i = 0 ; i < point_dim ; ++i) - { - for (int j = 0 ; j < Intrinsic_dimension + 1 ; ++j) - { - std::size_t data = (*it_c)->vertex(j)->data(); - const Point &p = m_points[data]; - center[i] += p[i]; - } - center[i] /= (Intrinsic_dimension + 1); - } - Point global_center(center.begin(), center.end());*/ + // Get the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS + // closest points std::vector simplex_pts; for (int i = 0 ; i < cur_dim + 1 ; ++i) @@ -1280,12 +1369,16 @@ private: m_k.translated_point_d_object(); typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); -#if defined(CGAL_TC_PERTURB_POSITION) && defined(CGAL_TC_PERTURB_POSITION_GLOBAL) + +# ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); -#endif +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); +# endif +# endif Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; @@ -1314,15 +1407,15 @@ private: it != neighbors.end() ; ++it) { -#ifdef CGAL_TC_PERTURB_WEIGHT +# ifdef CGAL_TC_PERTURB_WEIGHT m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); -#endif +# endif -#ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL +# ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL m_translations[*it] = k_scaled_vec(k_pt_to_vec( *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL Tr_point local_random_transl = cwp(*tr_point_on_sphere_generator++, 0); Vector &global_transl = m_translations[*it]; @@ -1334,20 +1427,20 @@ private: k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) ); } +# endif # endif -#endif } -#if !defined(CGAL_TC_GLOBAL_REFRESH) +# if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); -#endif +# endif // We will try the other cells next time (incident_cells is not // valid anymore here) break; } -#endif +#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY } return is_inconsistent; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 2d5f4b6e96d..c2c54be63a8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -36,11 +36,13 @@ #define CGAL_TC_VERBOSE //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -// Solving inconsistencies: only perturb the inconsistent simplex or more? +// Solving inconsistencies: only perturb the vertex, the simplex or more? +#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY //#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY -// Otherwise... -const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; +// Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS +// closest points +const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = -2; //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN From 499b702e9b3baaa8aaea6d599b9dd1046a74099f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 21 Jan 2015 13:40:48 +0100 Subject: [PATCH 185/487] Added the CGAL_TC_PERTURB_THE_1_STAR strategy --- .../include/CGAL/Tangential_complex.h | 90 ++++++++++++++++++- .../include/CGAL/Tangential_complex/config.h | 1 + 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c916b61a2f1..8fdac3e0795 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1315,8 +1315,13 @@ private: Tr_point local_random_transl = cwp(*tr_point_on_sphere_generator++, 0); Vector &global_transl = m_translations[tr_index]; - //Vector &global_transl = m_translations[ - // (*it_c)->vertex(rand()%tr.current_dimension())->data()]; + /*int idx; + do + { + idx = rand() % tr.current_dimension(); + } while ((*it_c)->vertex(idx) == center_vh); + Vector &global_transl = m_translations[ + (*it_c)->vertex(idx)->data()];*/ global_transl = k_constr_vec(m_ambiant_dim); const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; for (int i = 0 ; i < Intrinsic_dimension ; ++i) @@ -1329,6 +1334,85 @@ private: # endif # endif +# if !defined(CGAL_TC_GLOBAL_REFRESH) + refresh_tangential_complex(); +# endif + + // We will try the other cells next time (incident_cells is not + // valid anymore here) + break; + } + +//***************************************************************************** +// STRATEGY 3: perturb all the points of the 1-star +//***************************************************************************** +#elif defined(CGAL_TC_PERTURB_THE_1_STAR) + + // Inconsistent? + if (!is_simplex_consistent(*it_c, cur_dim)) + { + is_inconsistent = true; + + std::set c; + + typename std::vector::const_iterator it_c2 = + incident_cells.begin(); + // For each cell + for ( ; it_c2 != it_c_end ; ++it_c2) + { + for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) + { + std::size_t data = (*it_c2)->vertex(i)->data(); + c.insert(data); + } + } + +# ifdef CGAL_TC_PERTURB_POSITION + typename Tr_traits::Construct_weighted_point_d cwp = + local_tr_traits.construct_weighted_point_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); +# endif +# endif + + CGAL::Random rng; + for (std::set::iterator it=c.begin(); it!=c.end(); ++it) + { +# ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); +# endif + +# ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + m_translations[*it] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + Tr_point local_random_transl = + cwp(*tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[*it]; + global_transl = k_constr_vec(m_ambiant_dim); + const Tangent_space_basis &tsb = m_tangent_spaces[*it]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +# endif + } + # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif @@ -1339,7 +1423,7 @@ private: } //***************************************************************************** -// STRATEGY 3: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS +// STRATEGY 4: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points (to the power center of first the inconsistent cell) //***************************************************************************** #else diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index c2c54be63a8..baa361b3d39 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -39,6 +39,7 @@ // Solving inconsistencies: only perturb the vertex, the simplex or more? #define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY //#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY +//#define CGAL_TC_PERTURB_THE_1_STAR // Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points From 68b0f5839c5e7a50cbdef2f416006fb43f209fd6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 13:20:59 +0100 Subject: [PATCH 186/487] Added time limit to fix_inconsistencies() --- .../include/CGAL/Tangential_complex.h | 19 ++++++++++++++--- .../test_tangential_complex.cpp | 21 +++++++++++-------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8fdac3e0795..81d9e5cadc7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -70,6 +70,8 @@ namespace CGAL { using namespace Tangential_complex_; +enum Fix_inconsistencies_status { TC_FIXED = 0, TIME_LIMIT_REACHED }; + class Vertex_data { public: @@ -330,8 +332,12 @@ public: #endif } - unsigned int fix_inconsistencies() + // time_limit in seconds + Fix_inconsistencies_status fix_inconsistencies( + unsigned int &num_steps, double time_limit = 0.) { + Wall_clock_timer t; + typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); @@ -358,7 +364,7 @@ public: #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES bool done = false; - unsigned int num_steps = 0; + num_steps = 0; while (!done) { std::size_t num_inconsistent_local_tr = 0; @@ -446,9 +452,16 @@ public: ++num_steps; done = (num_inconsistent_local_tr == 0); + if (time_limit != 0 && t.elapsed() > time_limit) + { +#ifdef CGAL_TC_VERBOSE + std::cerr << "Time limit reached." << std::endl; +#endif + return TIME_LIMIT_REACHED; + } } - return num_steps; + return TC_FIXED; } diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 4acbb1a0843..5303a737c33 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -39,9 +39,11 @@ int main() const int INTRINSIC_DIMENSION = 3; const int AMBIENT_DIMENSION = 9; - typedef CGAL::Epick_d > Kernel; - typedef Kernel::FT FT; - typedef Kernel::Point_d Point; + typedef CGAL::Epick_d > Kernel; + typedef Kernel::FT FT; + typedef Kernel::Point_d Point; + typedef CGAL::Tangential_complex< + Kernel, INTRINSIC_DIMENSION, CGAL::Parallel_tag> TC; int i = 0; bool stop = false; @@ -82,10 +84,7 @@ int main() std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; - CGAL::Tangential_complex< - Kernel, - INTRINSIC_DIMENSION, - CGAL::Parallel_tag> tc(points.begin(), points.end(), k); + TC tc(points.begin(), points.end(), k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); @@ -108,7 +107,9 @@ int main() t.reset(); - tc.fix_inconsistencies(); + unsigned int num_fix_steps; + CGAL::Fix_inconsistencies_status fix_ret = + tc.fix_inconsistencies(num_fix_steps, 3000.); double fix_time = t.elapsed(); t.reset(); double export_after_time = -1.; @@ -135,7 +136,9 @@ int main() << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl << " * Export to OFF (before fix): " << export_before_time << std::endl - << " * Fix inconsistencies: " << fix_time << std::endl + << " * Fix inconsistencies: " + << (fix_ret == CGAL::TC_FIXED ? "FIXED / " : "NOT fixed / ") << fix_time + << " (" << num_fix_steps << " steps)" << std::endl << " * Export to OFF (after fix): " << export_after_time << std::endl << "================================================" << std::endl << std::endl; From 7ae8a6a4cc5f07693ab88a5394767cafeec7fb70 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 13:32:34 +0100 Subject: [PATCH 187/487] Better output --- .../test/Tangential_complex/test_tangential_complex.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 5303a737c33..5a5f82b25a5 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -136,9 +136,9 @@ int main() << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl << " * Export to OFF (before fix): " << export_before_time << std::endl - << " * Fix inconsistencies: " - << (fix_ret == CGAL::TC_FIXED ? "FIXED / " : "NOT fixed / ") << fix_time - << " (" << num_fix_steps << " steps)" << std::endl + << " * Fix inconsistencies: " << fix_time + << " (" << num_fix_steps << " steps) ==> " + << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl << " * Export to OFF (after fix): " << export_after_time << std::endl << "================================================" << std::endl << std::endl; From 0c876e6ba692870b43923b9eea70f7daa972a5c8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 14:00:33 +0100 Subject: [PATCH 188/487] Refactored try_to_solve function --- .../include/CGAL/Tangential_complex.h | 239 +++++------------- 1 file changed, 63 insertions(+), 176 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 81d9e5cadc7..1178ad84df8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1189,6 +1189,57 @@ private: }; #endif // CGAL_LINKED_WITH_TBB + void perturb(std::size_t point_idx) + { + CGAL::Random rng; + + // Perturb the weight? +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[point_idx] = rng.get_double(0., SQ_HALF_SPARSITY); +#endif + + // Perturb the position? +#ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator(m_ambiant_dim, 1); + + m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + const Tr_traits &local_tr_traits = + m_triangulations[point_idx].tr().geom_traits(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator(Intrinsic_dimension, 1); + + Tr_point local_random_transl = + local_tr_traits.construct_weighted_point_d_object()( + *tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[point_idx]; + global_transl = k_constr_vec(m_ambiant_dim); + const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +#endif // CGAL_TC_PERTURB_POSITION + } + bool try_to_solve_inconsistencies_in_a_local_triangulation( std::size_t tr_index) { @@ -1198,16 +1249,6 @@ private: //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif -#ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(m_ambiant_dim, 1); -# else - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(Intrinsic_dimension, 1); -# endif -#endif - Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); const Tr_traits &local_tr_traits = tr.geom_traits(); @@ -1240,51 +1281,8 @@ private: { is_inconsistent = true; -# ifdef CGAL_TC_PERTURB_POSITION - typename Tr_traits::Construct_weighted_point_d cwp = - local_tr_traits.construct_weighted_point_d_object(); - typename Tr_traits::Compute_coordinate_d coord = - local_tr_traits.compute_coordinate_d_object(); - - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - m_k.scaled_vector_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = - m_k.point_to_vector_d_object(); -# endif -# endif - - CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) - { -# ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); -# endif - -# ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - m_translations[*it] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - Tr_point local_random_transl = - cwp(*tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[*it]; - global_transl = k_constr_vec(m_ambiant_dim); - const Tangent_space_basis &tsb = m_tangent_spaces[*it]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - global_transl = k_transl( - global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) - ); - } -# endif -# endif - } + perturb(*it); # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); @@ -1302,50 +1300,16 @@ private: if (!is_simplex_consistent(*it_c, cur_dim)) { is_inconsistent = true; -# ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); -# endif - -# ifdef CGAL_TC_PERTURB_POSITION - typename Tr_traits::Construct_weighted_point_d cwp = - local_tr_traits.construct_weighted_point_d_object(); - typename Tr_traits::Compute_coordinate_d coord = - local_tr_traits.compute_coordinate_d_object(); - - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - m_k.scaled_vector_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); - -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = - m_k.point_to_vector_d_object(); - m_translations[tr_index] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - Tr_point local_random_transl = - cwp(*tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[tr_index]; - /*int idx; + + std::size_t idx = tr_index; + /*int k; do { - idx = rand() % tr.current_dimension(); - } while ((*it_c)->vertex(idx) == center_vh); - Vector &global_transl = m_translations[ - (*it_c)->vertex(idx)->data()];*/ - global_transl = k_constr_vec(m_ambiant_dim); - const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - global_transl = k_transl( - global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) - ); - } -# endif -# endif + k = rand() % tr.current_dimension(); + } while ((*it_c)->vertex(k) == center_vh); + std::size_t idx = (*it_c)->vertex(k)->data();*/ + + perturb(idx); # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); @@ -1369,7 +1333,7 @@ private: std::set c; typename std::vector::const_iterator it_c2 = - incident_cells.begin(); + incident_cells.begin(); // For each cell for ( ; it_c2 != it_c_end ; ++it_c2) { @@ -1380,51 +1344,8 @@ private: } } -# ifdef CGAL_TC_PERTURB_POSITION - typename Tr_traits::Construct_weighted_point_d cwp = - local_tr_traits.construct_weighted_point_d_object(); - typename Tr_traits::Compute_coordinate_d coord = - local_tr_traits.compute_coordinate_d_object(); - - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - m_k.scaled_vector_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = - m_k.point_to_vector_d_object(); -# endif -# endif - - CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) - { -# ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); -# endif - -# ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - m_translations[*it] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - Tr_point local_random_transl = - cwp(*tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[*it]; - global_transl = k_constr_vec(m_ambiant_dim); - const Tangent_space_basis &tsb = m_tangent_spaces[*it]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - global_transl = k_transl( - global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) - ); - } -# endif -# endif - } + perturb(*it); # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); @@ -1457,25 +1378,12 @@ private: typename Get_functor::type power_center(local_tr_traits); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); - typename Tr_traits::Construct_weighted_point_d cwp = - local_tr_traits.construct_weighted_point_d_object(); - //typename Tr_traits::Point_to_vector_d pt_to_vec = - // local_tr_traits.construct_point_to_vector_d_object(); typename Kernel::Translated_point_d k_transl = m_k.translated_point_d_object(); typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); -# ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = - m_k.point_to_vector_d_object(); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); -# endif -# endif Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; @@ -1504,28 +1412,7 @@ private: it != neighbors.end() ; ++it) { -# ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); -# endif - -# ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - m_translations[*it] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - Tr_point local_random_transl = - cwp(*tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[*it]; - global_transl = k_constr_vec(m_ambiant_dim); - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - global_transl = k_transl( - global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) - ); - } -# endif -# endif + perturb(*it); } # if !defined(CGAL_TC_GLOBAL_REFRESH) From b6a4f6d6008fdf3e197114f98f37d32a7f684fd3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 17:58:19 +0100 Subject: [PATCH 189/487] Dimensions can now be set at runtime by using Dynamic_dimension_tag --- .../include/CGAL/Tangential_complex.h | 81 ++++++++++--------- .../CGAL/Tangential_complex/Point_cloud.h | 5 +- .../CGAL/Tangential_complex/utilities.h | 2 - 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 1178ad84df8..fbe98160738 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -88,21 +88,21 @@ private: /// The class Tangential_complex represents a tangential complex template < typename Kernel, - int Intrinsic_dimension, + typename DimensionTag, typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Regular_triangulation < Regular_triangulation_euclidean_traits< - Epick_d > >, + Epick_d >, Triangulation_data_structure < typename Regular_triangulation_euclidean_traits< - Epick_d > >::Dimension, + Epick_d >::Dimension, Triangulation_vertex > >, Vertex_data >, + Epick_d >, Vertex_data >, Triangulation_full_cell > > > + Epick_d > > > > > @@ -186,8 +186,10 @@ public: /// Constructor for a range of points template Tangential_complex(InputIterator first, InputIterator last, + int intrinsic_dimension, const Kernel &k = Kernel()) : m_k(k), + m_intrinsic_dimension(intrinsic_dimension), m_points(first, last), m_points_ds(m_points), m_ambiant_dim(k.point_dimension_d_object()(*first)) @@ -219,10 +221,12 @@ public: m_weights.resize(m_points.size(), FT(0)); #endif #ifdef CGAL_TC_PERTURB_POSITION - m_translations.resize(m_points.size()); + m_translations.resize(m_points.size(), + m_k.construct_vector_d_object()(m_ambiant_dim)); #endif #ifdef CGAL_TC_EXPORT_NORMALS - m_normals.resize(m_points.size()); + m_normals.resize(m_points.size(), + m_k.construct_vector_d_object()(m_ambiant_dim)); #endif #ifdef CGAL_LINKED_WITH_TBB @@ -548,7 +552,7 @@ public: << std::endl; } - if (Intrinsic_dimension < 1 || Intrinsic_dimension > 3) + if (m_intrinsic_dimension < 1 || m_intrinsic_dimension > 3) { std::cerr << "Error: export_to_off => intrinsic dimension should be " "between 1 and 3." @@ -614,12 +618,12 @@ public: cit != ambient_dt.finite_full_cells_end() ; ++cit ) { CGAL::Combination_enumerator combi( - Intrinsic_dimension + 1, 0, ambient_dim + 1); + m_intrinsic_dimension + 1, 0, ambient_dim + 1); for ( ; !combi.finished() ; ++combi) { Indexed_simplex simplex; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) simplex.insert(cit.base()->vertex(combi[i])->data()); amb_dt_simplices.insert(simplex); @@ -785,7 +789,7 @@ private: { //std::cerr << "***********************************************" << std::endl; Triangulation &local_tr = - m_triangulations[i].construct_triangulation(Intrinsic_dimension); + m_triangulations[i].construct_triangulation(m_intrinsic_dimension); const Tr_traits &local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); @@ -831,7 +835,7 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(Intrinsic_dimension, ORIGIN), + local_tr_traits.construct_point_d_object()(m_intrinsic_dimension, ORIGIN), #ifdef CGAL_TC_PERTURB_WEIGHT m_weights[i] #else @@ -895,7 +899,7 @@ private: vh->data() = neighbor_point_idx; // Let's recompute star_sphere_squared_radius - if (local_tr.current_dimension() >= Intrinsic_dimension) + if (local_tr.current_dimension() >= m_intrinsic_dimension) { star_sphere_squared_radius = 0; // Get the incident cells and look for the biggest circumsphere @@ -989,7 +993,7 @@ private: // eigenvalues Tangent_space_basis ts; for (int i = m_ambiant_dim - 1 ; - i >= m_ambiant_dim - Intrinsic_dimension ; + i >= m_ambiant_dim - m_intrinsic_dimension ; --i) { ts.push_back(constr_vec( @@ -1000,8 +1004,8 @@ private: #ifdef CGAL_TC_EXPORT_NORMALS *p_normal = constr_vec( m_ambiant_dim, - eig.eigenvectors().col(m_ambiant_dim - Intrinsic_dimension - 1).data(), - eig.eigenvectors().col(m_ambiant_dim - Intrinsic_dimension - 1).data() + m_ambiant_dim); + eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data(), + eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data() + m_ambiant_dim); #endif //************************************************************************* @@ -1024,7 +1028,7 @@ private: typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts; - ts.reserve(Intrinsic_dimension); + ts.reserve(m_intrinsic_dimension); ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); @@ -1037,7 +1041,7 @@ private: //Vector t1(12., 15., 65.); //Vector t2(32., 5., 85.); //Tangent_space_basis ts; - //ts.reserve(Intrinsic_dimension); + //ts.reserve(m_intrinsic_dimension); //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); //return compute_gram_schmidt_basis(ts, m_k); @@ -1056,8 +1060,8 @@ private: std::vector coords; // Ambiant-space coords of the projected point - coords.reserve(Intrinsic_dimension); - for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) + coords.reserve(m_intrinsic_dimension); + for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { // Compute the inner product p * ts[i] Vector v = diff_points(p, origin); @@ -1065,7 +1069,7 @@ private: coords.push_back(coord); } - return Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()); + return Tr_bare_point(m_intrinsic_dimension, coords.begin(), coords.end()); } // Project the point in the tangent space @@ -1087,8 +1091,8 @@ private: std::vector coords; // Ambiant-space coords of the projected point std::vector p_proj(ccci(origin), ccci(origin, 0)); - coords.reserve(Intrinsic_dimension); - for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) + coords.reserve(m_intrinsic_dimension); + for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { // Compute the inner product p * ts[i] FT coord = inner_pdct(v, ts[i]); @@ -1104,7 +1108,7 @@ private: return tr_traits.construct_weighted_point_d_object() ( tr_traits.construct_point_d_object()( - Intrinsic_dimension, coords.begin(), coords.end()), + m_intrinsic_dimension, coords.begin(), coords.end()), w - m_k.squared_distance_d_object()(p, projected_pt) ); } @@ -1221,7 +1225,7 @@ private: m_k.scaled_vector_d_object(); CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(Intrinsic_dimension, 1); + tr_point_on_sphere_generator(m_intrinsic_dimension, 1); Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( @@ -1229,7 +1233,7 @@ private: Vector &global_transl = m_translations[point_idx]; global_transl = k_constr_vec(m_ambiant_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_transl = k_transl( global_transl, @@ -1388,7 +1392,7 @@ private: Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_center = k_transl( global_center, @@ -1397,7 +1401,7 @@ private: KNS_range kns_range = m_points_ds.query_ANN( global_center, - Intrinsic_dimension + 1 + m_intrinsic_dimension + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; @@ -1439,10 +1443,10 @@ private: return os; } - // If Intrinsic_dimension = 1, we output each point two times + // If m_intrinsic_dimension = 1, we output each point two times // to be able to export each segment as a flat triangle with 3 different // indices (otherwise, Meshlab detects degenerated simplices) - const int N = (Intrinsic_dimension == 1 ? 2 : 1); + const int N = (m_intrinsic_dimension == 1 ? 2 : 1); const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors @@ -1487,11 +1491,11 @@ private: std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) { - // If Intrinsic_dimension = 1, each point is output two times + // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) - int factor = (Intrinsic_dimension == 1 ? 2 : 1); + int factor = (m_intrinsic_dimension == 1 ? 2 : 1); int OFF_simplices_dim = - (Intrinsic_dimension == 1 ? 3 : Intrinsic_dimension + 1); + (m_intrinsic_dimension == 1 ? 3 : m_intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; typename Tr_container::const_iterator it_tr = m_triangulations.begin(); @@ -1502,7 +1506,7 @@ private: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - if (tr.current_dimension() < Intrinsic_dimension) + if (tr.current_dimension() < m_intrinsic_dimension) continue; // Color for this star @@ -1526,14 +1530,14 @@ private: std::set c; std::stringstream sstr_c; std::size_t data; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) { data = (*it_c)->vertex(i)->data(); sstr_c << data*factor << " "; c.insert(data); } // See export_vertices_to_off - if (Intrinsic_dimension == 1) + if (m_intrinsic_dimension == 1) sstr_c << (data*factor + 1) << " "; bool excluded = @@ -1564,13 +1568,13 @@ private: { os << OFF_simplices_dim << " "; std::size_t data; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) { data = (*it_c)->vertex(i)->data(); os << data*factor << " "; } // See export_vertices_to_off - if (Intrinsic_dimension == 1) + if (m_intrinsic_dimension == 1) os << (data*factor + 1) << " "; ++num_simplices; @@ -1603,6 +1607,7 @@ private: private: const Kernel m_k; + const int m_intrinsic_dimension; const int m_ambiant_dim; Points m_points; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 4c6c2904003..0ea59a5f208 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -117,9 +117,10 @@ public: static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar /// Constructor + /// "points" must not be empty Point_cloud_data_structure(Point_container_ &points, Kernel const& k) : m_adaptor(points, k), - m_kd_tree(AMB_DIM, + m_kd_tree(k.point_dimension_d_object()(*points.begin()), m_adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) { @@ -243,8 +244,6 @@ public: typedef typename Incremental_neighbor_search::iterator INS_iterator; typedef Incremental_neighbor_search INS_range; - static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar - /// Constructor Point_cloud_data_structure(Point_container_ const& points) : m_points(points), diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 3797268d6ae..fa55b4f332c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -39,8 +39,6 @@ namespace Tangential_complex_ { typedef typename K::Vector_d Vector; typedef std::vector Basis; - const int D = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar - // Kernel functors typename K::Squared_length_d sqlen = kernel.squared_length_d_object(); typename K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); From d4c289daee925b52ad9b1451dce2ddb1da246d4c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 18:09:20 +0100 Subject: [PATCH 190/487] Better benchmark: scripts, logs --- .../Tangential_complex/benchmark_tc.cpp | 350 ++++++++++++------ 1 file changed, 238 insertions(+), 112 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 26606958ab2..cc788b7152d 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -1,3 +1,12 @@ +//#undef CGAL_LINKED_WITH_TBB // CJTODO TEMP + +// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB +// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/) +#ifdef _DEBUG +# define TBB_USE_THREADING_TOOL +#endif + +#include #include #include #include @@ -17,6 +26,15 @@ #define CGAL_TC_SET_PERFORMANCE_DATA(value_name, value) \ XML_perf_data::set(value_name, value); +const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt"; + +typedef CGAL::Epick_d Kernel; +typedef Kernel::FT FT; +typedef Kernel::Point_d Point; +typedef CGAL::Tangential_complex< + Kernel, CGAL::Dynamic_dimension_tag, + CGAL::Parallel_tag> TC; + class XML_perf_data { public: @@ -59,16 +77,17 @@ protected: static std::vector construct_subelements_names() { std::vector subelements; - subelements.push_back("Name"); + subelements.push_back("Input"); subelements.push_back("Intrinsic_dim"); subelements.push_back("Ambient_dim"); subelements.push_back("Num_points"); - subelements.push_back("Noise"); - subelements.push_back("Info"); + subelements.push_back("Sparsity"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); + subelements.push_back("Fix_successful"); subelements.push_back("Fix_time"); subelements.push_back("Fix_steps"); + subelements.push_back("Info"); return subelements; } @@ -103,128 +122,235 @@ const double NOISE = 0.01; const int NUM_POINTS = 30000; #endif +void make_tc(std::vector &points, int intrinsic_dim, + double sparsity = 0., double time_limit_for_fix = 0.) +{ + Kernel k; + Wall_clock_timer t; + + int ambient_dim = k.point_dimension_d_object()(*points.begin()); + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_gen; +#endif + +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set generated in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif + + if (sparsity != 0.) + { + std::size_t num_points_before = points.size(); + points = sparsify_point_set( + k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + std::cerr << "Number of points before/after sparsification: " + << num_points_before << " / " << points.size() << std::endl; + } + + CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); + CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); + + TC tc(points.begin(), points.end(), intrinsic_dim, k); + double init_time = t.elapsed(); t.reset(); + + tc.compute_tangential_complex(); + double computation_time = t.elapsed(); t.reset(); + + std::set > incorrect_simplices; + //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + + double export_before_time = -1.; + if (intrinsic_dim <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/test_tc_" << intrinsic_dim + << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + export_before_time = t.elapsed(); t.reset(); + } + + + t.reset(); + unsigned int num_fix_steps; + CGAL::Fix_inconsistencies_status fix_ret = + tc.fix_inconsistencies(num_fix_steps, time_limit_for_fix); + double fix_time = t.elapsed(); t.reset(); + + double export_after_time = -1.; + if (intrinsic_dim <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/test_tc_" << intrinsic_dim + << "_in_R" << ambient_dim << "_AFTER_FIX.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + export_after_time = t.elapsed(); t.reset(); + } + /*else + tc.number_of_inconsistent_simplices();*/ + + std::cerr << std::endl + << "================================================" << std::endl + << "Number of vertices: " << tc.number_of_vertices() << std::endl + << "Computation times (seconds): " << std::endl + << " * Tangential complex: " << init_time + computation_time + << std::endl + << " - Init + kd-tree = " << init_time << std::endl + << " - TC computation = " << computation_time << std::endl + << " * Export to OFF (before fix): " << export_before_time << std::endl + << " * Fix inconsistencies: " << fix_time + << " (" << num_fix_steps << " steps) ==> " + << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl + << " * Export to OFF (after fix): " << export_after_time << std::endl + << "================================================" << std::endl + << std::endl; + + CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); + CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_successful", + (fix_ret == CGAL::TC_FIXED ? "Y" : "N")); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_time", fix_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_steps", num_fix_steps); + CGAL_TC_SET_PERFORMANCE_DATA("Info", ""); +} + int main() { #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG - tbb::task_scheduler_init init(1); + int num_threads = 1; # else - tbb::task_scheduler_init init(10); + int num_threads = 10; # endif #endif - const int INTRINSIC_DIMENSION = 2; - const int AMBIENT_DIMENSION = 4; - - typedef CGAL::Epick_d > Kernel; - typedef Kernel::FT FT; - typedef Kernel::Point_d Point; - - bool stop = false; - //for (int i = 0, NUM_POINTS = 10000 ; - // NUM_POINTS <= 50000 && !stop ; - // ++i, NUM_POINTS += (i%3 == 0 ? 5000 : 0)) - for (int i = 0 ; i < 5 && !stop ; ++i) + int seed = CGAL::default_random.get_int(0, 1<<30); + CGAL::default_random = CGAL::Random(); + std::cerr << "Random seed = " << seed << std::endl; + + std::ifstream script_file; + script_file.open(BENCHMARK_SCRIPT_FILENAME); + // Script? + // Script file format: each line gives + // - Filename (point set) or "generate_XXX" (point set generation) + // - Ambient dim + // - Intrinsic dim + // - Number of iterations with these parameters + if (script_file.is_open()) { - Kernel k; - 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; + int i = 1; +#ifdef CGAL_LINKED_WITH_TBB +# ifdef BENCHMARK_WITH_1_TO_MAX_THREADS + for(num_threads = 1 ; + num_threads <= tbb::task_scheduler_init::default_num_threads() ; + ++num_threads) +# endif #endif - //std::vector points; - //load_points_from_file( - // "data/points_10_10k.cin", std::back_inserter(points)/*, 600*/); - - std::vector points = - //generate_points_on_circle_2(NUM_POINTS, 3.); - //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); - //generate_points_on_plane(NUM_POINTS); - //generate_points_on_sphere_3(NUM_POINTS, 3.0); - //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); - //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3., NOISE); - //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); - - - CGAL_TC_SET_PERFORMANCE_DATA("Name", "Klein bottle 4D"); - CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", INTRINSIC_DIMENSION); - CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", AMBIENT_DIMENSION); - CGAL_TC_SET_PERFORMANCE_DATA("Noise", NOISE); - XML_perf_data::set("Info", "" -#ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS - "ONLY_CHANGE_SIMPLEX_WEIGHTS " -#endif -#ifdef CGAL_TC_GLOBAL_REFRESH - "GLOBAL_REFRESH " -#endif - ); - -#ifdef CGAL_TC_PROFILING - std::cerr << "Point set generated in " << t_gen.elapsed() - << " seconds." << std::endl; -#endif - - std::cerr << "Number of points before sparsification: " - << points.size() << std::endl; - points = sparsify_point_set( - k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); - std::cerr << "Number of points after sparsification: " - << points.size() << std::endl; - - CGAL::Tangential_complex< - Kernel, - INTRINSIC_DIMENSION, - CGAL::Parallel_tag> tc(points.begin(), points.end(), k); - double init_time = t.elapsed(); t.reset(); - - //tc.estimate_intrinsic_dimension(); - tc.compute_tangential_complex(); - double computation_time = t.elapsed(); t.reset(); - - std::set > incorrect_simplices; - //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); - - t.reset(); - unsigned int num_fix_steps = tc.fix_inconsistencies(); - double fix_time = t.elapsed(); t.reset(); - - double export_time = -1.; - if (INTRINSIC_DIMENSION <= 3) + /*for (Concurrent_mesher_config::get().num_work_items_per_batch = 5 ; + Concurrent_mesher_config::get().num_work_items_per_batch < 100 ; + Concurrent_mesher_config::get().num_work_items_per_batch += 5)*/ { - t.reset(); - std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION - << "_in_R" << AMBIENT_DIMENSION << ".off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); - double export_time = t.elapsed(); t.reset(); +#ifdef CGAL_LINKED_WITH_TBB + tbb::task_scheduler_init init( + num_threads > 0 ? num_threads : tbb::task_scheduler_init::automatic); +#endif + + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' found." << std::endl; + script_file.seekg(0); + while (script_file.good()) + { + std::string line; + std::getline(script_file, line); + if (line.size() > 1 && line[0] != '#') + { + std::cerr << std::endl << std::endl; + std::cerr << "*****************************************" << std::endl; + std::cerr << "******* " << line << std::endl; + std::cerr << "*****************************************" << std::endl; + std::stringstream sstr(line); + + std::string input; + int ambient_dim; + int intrinsic_dim; + double sparsity; + double time_limit_for_fix; + int num_iteration; + sstr >> input; + sstr >> ambient_dim; + sstr >> intrinsic_dim; + sstr >> sparsity; + sstr >> time_limit_for_fix; + sstr >> num_iteration; + + for (int j = 0 ; j < num_iteration ; ++j) + { + std::string input_stripped = input; + size_t slash_index = input_stripped.find_last_of('/'); + if (slash_index == std::string::npos) + slash_index = input_stripped.find_last_of('\\'); + if (slash_index == std::string::npos) + slash_index = 0; + else + ++slash_index; + input_stripped = input_stripped.substr( + slash_index, input_stripped.find_last_of('.') - slash_index); + + CGAL_TC_SET_PERFORMANCE_DATA("Input", input_stripped); + CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", ambient_dim); + CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", intrinsic_dim); +#ifdef CGAL_LINKED_WITH_TBB + CGAL_TC_SET_PERFORMANCE_DATA( + "Num_threads", + (num_threads == -1 ? tbb::task_scheduler_init::default_num_threads() : num_threads)); +#else + CGAL_TC_SET_PERFORMANCE_DATA("Num_threads", "N/A"); +#endif + + std::cerr << std::endl << "TC #" << i << "..." << std::endl; + + std::vector points; + + + //points = + //generate_points_on_circle_2(NUM_POINTS, 3.); + //generate_points_on_moment_curve(NUM_POINTS, ambient_dim, 0., 1.); + //generate_points_on_plane(NUM_POINTS); + //generate_points_on_sphere_3(NUM_POINTS, 3.0); + //generate_points_on_sphere_d(NUM_POINTS, ambient_dim, 3.0); + //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3., NOISE); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + + /*if (input == "Klein_function") + make_mesh_implicit(facet_approx, facet_sizing, cell_sizing, Klein_function(), input); + else*/ + { + load_points_from_file( + input, std::back_inserter(points)/*, 600*/); + make_tc(points, intrinsic_dim, sparsity, time_limit_for_fix); + } + + std::cerr << "TC #" << i++ << " done." << std::endl; + std::cerr << std::endl << "---------------------------------" << std::endl << std::endl; + + XML_perf_data::commit(); + } + } + } + script_file.seekg(0); + script_file.clear(); } - /*else - tc.number_of_inconsistent_simplices();*/ - - std::cerr << std::endl - << "================================================" << std::endl - << "Number of vertices: " << tc.number_of_vertices() << std::endl - << "Computation times (seconds): " << std::endl - << " * Tangential complex: " << init_time + computation_time < Date: Mon, 26 Jan 2015 18:10:28 +0100 Subject: [PATCH 191/487] Script --- .../benchmark/Tangential_complex/benchmark_script.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt new file mode 100644 index 00000000000..5dde2a2a389 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -0,0 +1,2 @@ +#Input AMB INTR SPARSITY TIME_LIMIT NUM_ITERATIONS +data/SO3_10000.txt 9 3 0.05 60 5 \ No newline at end of file From bb8d57583889018a0fb01dbdf7d6aea07f7dd845 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Jan 2015 16:28:22 +0100 Subject: [PATCH 192/487] Updated test according to the latest changes in the TC --- .../Tangential_complex/test_tangential_complex.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 5a5f82b25a5..f9f359ec450 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -6,6 +6,7 @@ # define TBB_USE_THREADING_TOOL #endif +#include #include #include #include @@ -28,6 +29,11 @@ int main() { +#if defined(CHECK_MEMORY_LEAKS_ON_MSVC) && defined(_MSC_VER) + _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); +#endif + CGAL::set_error_behaviour(CGAL::ABORT); + #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG tbb::task_scheduler_init init(1); @@ -43,7 +49,8 @@ int main() typedef Kernel::FT FT; typedef Kernel::Point_d Point; typedef CGAL::Tangential_complex< - Kernel, INTRINSIC_DIMENSION, CGAL::Parallel_tag> TC; + Kernel, CGAL::Dimension_tag, + CGAL::Parallel_tag> TC; int i = 0; bool stop = false; @@ -84,7 +91,7 @@ int main() std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; - TC tc(points.begin(), points.end(), k); + TC tc(points.begin(), points.end(), INTRINSIC_DIMENSION, k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); From 0f0228cf5f08c5f37b56d951605d069d100504a6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 14:39:29 +0100 Subject: [PATCH 193/487] The benchmark can now generate points --- .../Tangential_complex/benchmark_script.txt | 14 ++- .../Tangential_complex/benchmark_tc.cpp | 84 +++++++++---- .../test/Tangential_complex/test_utilities.h | 115 +++++++++--------- 3 files changed, 130 insertions(+), 83 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 5dde2a2a389..cf2e5e11f60 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -1,2 +1,12 @@ -#Input AMB INTR SPARSITY TIME_LIMIT NUM_ITERATIONS -data/SO3_10000.txt 9 3 0.05 60 5 \ No newline at end of file +#Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY TIME_LIMIT NUM_ITERATIONS +#data/SO3_10000.txt - - - 0 9 3 0.05 60 1 + +############### Generated point sets ################### +#generate_sphere_d 3 - - 30000 3 2 0.05 60 1 +#generate_moment_curve 0 1 - 30000 6 1 0.05 60 1 +#generate_plane - - - 30000 3 2 0.05 60 1 +#generate_sphere_d 3 - - 30000 3 2 0.05 60 1 +#generate_sphere_d 3 - - 1000 6 5 0.05 60 1 +generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 +generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 +generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index cc788b7152d..b0fec26cdca 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -14,7 +14,10 @@ #include "../../test/Tangential_complex/test_utilities.h" +#include +#include +#include #include #include @@ -115,13 +118,6 @@ protected: XML_exporter::Element_with_map m_current_element; }; -const double NOISE = 0.01; -#ifdef _DEBUG - const int NUM_POINTS = 50; -#else - const int NUM_POINTS = 30000; -#endif - void make_tc(std::vector &points, int intrinsic_dim, double sparsity = 0., double time_limit_for_fix = 0.) { @@ -267,6 +263,8 @@ int main() std::getline(script_file, line); if (line.size() > 1 && line[0] != '#') { + boost::replace_all(line, "\t", " "); + boost::trim_all(line); std::cerr << std::endl << std::endl; std::cerr << "*****************************************" << std::endl; std::cerr << "******* " << line << std::endl; @@ -274,12 +272,20 @@ int main() std::stringstream sstr(line); std::string input; + std::string param1; + std::string param2; + std::string param3; + std::size_t num_points; int ambient_dim; int intrinsic_dim; double sparsity; double time_limit_for_fix; int num_iteration; sstr >> input; + sstr >> param1; + sstr >> param2; + sstr >> param3; + sstr >> num_points; sstr >> ambient_dim; sstr >> intrinsic_dim; sstr >> sparsity; @@ -313,29 +319,59 @@ int main() std::cerr << std::endl << "TC #" << i << "..." << std::endl; std::vector points; - - //points = - //generate_points_on_circle_2(NUM_POINTS, 3.); - //generate_points_on_moment_curve(NUM_POINTS, ambient_dim, 0., 1.); - //generate_points_on_plane(NUM_POINTS); - //generate_points_on_sphere_3(NUM_POINTS, 3.0); - //generate_points_on_sphere_d(NUM_POINTS, ambient_dim, 3.0); - //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - //generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3., NOISE); - //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); - - /*if (input == "Klein_function") - make_mesh_implicit(facet_approx, facet_sizing, cell_sizing, Klein_function(), input); - else*/ + if (input == "generate_moment_curve") + { + points = generate_points_on_moment_curve( + num_points, ambient_dim, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else if (input == "generate_plane") + { + points = generate_points_on_plane(num_points); + } + else if (input == "generate_sphere_d") + { + points = generate_points_on_sphere_d( + num_points, ambient_dim, + std::atof(param1.c_str())); + } + else if (input == "generate_klein_bottle_3D") + { + points = generate_points_on_klein_bottle_3D( + num_points, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else if (input == "generate_klein_bottle_4D") + { + points = generate_points_on_klein_bottle_4D( + num_points, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else if (input == "generate_klein_bottle_variant_5D") + { + points = generate_points_on_klein_bottle_variant_5D( + num_points, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else { load_points_from_file( input, std::back_inserter(points)/*, 600*/); - make_tc(points, intrinsic_dim, sparsity, time_limit_for_fix); } - std::cerr << "TC #" << i++ << " done." << std::endl; - std::cerr << std::endl << "---------------------------------" << std::endl << std::endl; + if (!points.empty()) + { + make_tc(points, intrinsic_dim, sparsity, time_limit_for_fix); + + std::cerr << "TC #" << i++ << " done." << std::endl; + std::cerr << std::endl << "---------------------------------" + << std::endl << std::endl; + } + else + { + std::cerr << "TC #" << i++ << ": no points loaded." << std::endl; + } XML_perf_data::commit(); } diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index f953736efd7..4e05725c991 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -30,6 +30,7 @@ #include #include #include +#include #include // Actually, this is very slow because the "m_points_ds->insert" @@ -82,6 +83,52 @@ private: }; #endif +// construct_point: dim 2 +template +typename Kernel::Point_d construct_point( + const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2) +{ + typename Kernel::FT tab[2]; + tab[0] = x1; tab[1] = x2; + return k.construct_point_d_object()(2, &tab[0], &tab[2]); +} + +// construct_point: dim 3 +template +typename Kernel::Point_d construct_point( + const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3) +{ + typename Kernel::FT tab[3]; + tab[0] = x1; tab[1] = x2; tab[2] = x3; + return k.construct_point_d_object()(3, &tab[0], &tab[3]); +} + +// construct_point: dim 4 +template +typename Kernel::Point_d construct_point( + const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3, + typename Kernel::FT x4) +{ + typename Kernel::FT tab[4]; + tab[0] = x1; tab[1] = x2; tab[2] = x3; tab[3] = x4; + return k.construct_point_d_object()(4, &tab[0], &tab[4]); +} + +// construct_point: dim 5 +template +typename Kernel::Point_d construct_point( + const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3, + typename Kernel::FT x4, typename Kernel::FT x5) +{ + typename Kernel::FT tab[5]; + tab[0] = x1; tab[1] = x2; tab[2] = x3; tab[3] = x4; tab[4] = x5; + return k.construct_point_d_object()(5, &tab[0], &tab[5]); +} + template std::vector sparsify_point_set( @@ -181,6 +228,7 @@ std::vector generate_points_on_plane(std::size_t num_p { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; std::vector points; points.reserve(num_points); @@ -191,7 +239,7 @@ std::vector generate_points_on_plane(std::size_t num_p { FT x = rng.get_double(0, 5); FT y = rng.get_double(0, 5); - Point p = Kernel().construct_point_d_object()(x, y, 0); + Point p = construct_point(k, x, y, FT(0)); #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) ++i; @@ -210,6 +258,7 @@ std::vector generate_points_on_moment_curve( { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; std::vector points; points.reserve(num_points); @@ -223,7 +272,7 @@ std::vector generate_points_on_moment_curve( coords.reserve(dim); for (int p = 1 ; p <= dim ; ++p) coords.push_back(std::pow(CGAL::to_double(x), p)); - Point p = Kernel().construct_point_d_object()( + Point p = k.construct_point_d_object()( dim, coords.begin(), coords.end()); #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) @@ -236,56 +285,6 @@ std::vector generate_points_on_moment_curve( return points; } -template -std::vector generate_points_on_circle_2( - std::size_t num_points, double radius) -{ - typedef typename Kernel::Point_d Point; - CGAL::Random_points_on_circle_2 generator(radius); - std::vector points; - points.reserve(num_points); -#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER - Point_sparsifier > 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; -} - -template -std::vector generate_points_on_sphere_3( - std::size_t num_points, double radius) -{ - typedef typename Kernel::Point_d Point; - CGAL::Random_points_on_sphere_3 generator(radius); - std::vector points; - points.reserve(num_points); -#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER - Point_sparsifier > 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; -} - template std::vector generate_points_on_sphere_d( std::size_t num_points, int dim, double radius) @@ -318,6 +317,7 @@ std::vector generate_points_on_klein_bottle_3D( { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; // if uniform @@ -345,7 +345,7 @@ std::vector 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); - Point p = Kernel().construct_point_d_object()( + Point p = construct_point(k, (a + b*tmp)*cos(u), (a + b*tmp)*sin(u), b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v))); @@ -367,6 +367,7 @@ std::vector generate_points_on_klein_bottle_4D( { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; // if uniform @@ -393,12 +394,11 @@ std::vector generate_points_on_klein_bottle_4D( u = rng.get_double(0, 6.2832); v = rng.get_double(0, 6.2832); } - Point p = Kernel().construct_point_d_object()( - Kernel().construct_point_d_object()( + Point p = construct_point(k, (a + b*cos(v))*cos(u) + (noise == 0. ? 0. : rng.get_double(0, noise)), (a + b*cos(v))*sin(u) + (noise == 0. ? 0. : rng.get_double(0, noise)), b*sin(v)*cos(u/2) + (noise == 0. ? 0. : rng.get_double(0, noise)), - b*sin(v)*sin(u/2) + (noise == 0. ? 0. : rng.get_double(0, noise)))); + b*sin(v)*sin(u/2) + (noise == 0. ? 0. : rng.get_double(0, noise))); #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) ++i; @@ -419,6 +419,7 @@ generate_points_on_klein_bottle_variant_5D( { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; // if uniform @@ -451,7 +452,7 @@ generate_points_on_klein_bottle_variant_5D( FT x4 = b*sin(v)*sin(u/2); FT x5 = x1 + x2 + x3 + x4; - Point p = Kernel().construct_point_d_object()(x1, x2, x3, x4, x5); + Point p = construct_point(k, x1, x2, x3, x4, x5); #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) ++i; From b42bdf8c3c79612da5c38832a0f07cfaeccd2c6e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 14:41:00 +0100 Subject: [PATCH 194/487] Change CGAL_TC_NUMBER_OF_PERTURBED_POINTS => macro --- Tangential_complex/include/CGAL/Tangential_complex.h | 3 +-- Tangential_complex/include/CGAL/Tangential_complex/config.h | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fbe98160738..7308a1a144e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1401,8 +1401,7 @@ private: KNS_range kns_range = m_points_ds.query_ANN( global_center, - m_intrinsic_dimension + 1 - + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS); + CGAL_TC_NUMBER_OF_PERTURBED_POINTS(m_intrinsic_dimension)); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; nn_it != kns_range.end() ; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index baa361b3d39..09abb486a95 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -37,13 +37,14 @@ //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES // Solving inconsistencies: only perturb the vertex, the simplex or more? -#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY +//#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY //#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY //#define CGAL_TC_PERTURB_THE_1_STAR // Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points -const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = -2; +//#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) +#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN From 19a229254a6cda7275afafa5caad1c96bb955dcd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:06:36 +0100 Subject: [PATCH 195/487] More stats + fixed a bug when there are infinite cells in the star --- .../Tangential_complex/benchmark_tc.cpp | 31 ++++++++++++++----- .../include/CGAL/Tangential_complex.h | 13 +++++++- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index b0fec26cdca..28fb56d5ae4 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -83,8 +83,11 @@ protected: subelements.push_back("Input"); subelements.push_back("Intrinsic_dim"); subelements.push_back("Ambient_dim"); - subelements.push_back("Num_points"); subelements.push_back("Sparsity"); + subelements.push_back("Num_points_in_input"); + subelements.push_back("Num_points"); + subelements.push_back("Initial_num_inconsistent_local_tr"); + subelements.push_back("Best_num_inconsistent_local_tr"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); subelements.push_back("Fix_successful"); @@ -119,7 +122,8 @@ protected: }; void make_tc(std::vector &points, int intrinsic_dim, - double sparsity = 0., double time_limit_for_fix = 0.) + double sparsity = 0., double time_limit_for_fix = 0., + const char *input_name = "tc") { Kernel k; Wall_clock_timer t; @@ -134,6 +138,8 @@ void make_tc(std::vector &points, int intrinsic_dim, std::cerr << "Point set generated in " << t_gen.elapsed() << " seconds." << std::endl; #endif + + CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); if (sparsity != 0.) { @@ -144,8 +150,8 @@ void make_tc(std::vector &points, int intrinsic_dim, << num_points_before << " / " << points.size() << std::endl; } - CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); + CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); TC tc(points.begin(), points.end(), intrinsic_dim, k); double init_time = t.elapsed(); t.reset(); @@ -161,7 +167,7 @@ void make_tc(std::vector &points, int intrinsic_dim, { t.reset(); std::stringstream output_filename; - output_filename << "output/test_tc_" << intrinsic_dim + output_filename << "output/" << input_name << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); @@ -171,16 +177,24 @@ void make_tc(std::vector &points, int intrinsic_dim, t.reset(); unsigned int num_fix_steps; - CGAL::Fix_inconsistencies_status fix_ret = - tc.fix_inconsistencies(num_fix_steps, time_limit_for_fix); + std::size_t initial_num_inconsistent_local_tr; + std::size_t best_num_inconsistent_local_tr; + CGAL::Fix_inconsistencies_status fix_ret = tc.fix_inconsistencies( + num_fix_steps, initial_num_inconsistent_local_tr, + best_num_inconsistent_local_tr, time_limit_for_fix); double fix_time = t.elapsed(); t.reset(); + + CGAL_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", + initial_num_inconsistent_local_tr); + CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", + best_num_inconsistent_local_tr); double export_after_time = -1.; if (intrinsic_dim <= 3) { t.reset(); std::stringstream output_filename; - output_filename << "output/test_tc_" << intrinsic_dim + output_filename << "output/" << input_name << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); @@ -362,7 +376,8 @@ int main() if (!points.empty()) { - make_tc(points, intrinsic_dim, sparsity, time_limit_for_fix); + make_tc(points, intrinsic_dim, sparsity, + time_limit_for_fix, input.c_str()); std::cerr << "TC #" << i++ << " done." << std::endl; std::cerr << std::endl << "---------------------------------" diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7308a1a144e..c2ce1049c88 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -338,7 +338,8 @@ public: // time_limit in seconds Fix_inconsistencies_status fix_inconsistencies( - unsigned int &num_steps, double time_limit = 0.) + unsigned int &num_steps, std::size_t &initial_num_inconsistent_local_tr, + std::size_t &best_num_inconsistent_local_tr, double time_limit = 0.) { Wall_clock_timer t; @@ -368,6 +369,7 @@ public: #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES bool done = false; + best_num_inconsistent_local_tr = m_triangulations.size(); num_steps = 0; while (!done) { @@ -454,6 +456,12 @@ public: # endif #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES + if (num_steps == 0) + initial_num_inconsistent_local_tr = num_inconsistent_local_tr; + + if (num_inconsistent_local_tr < best_num_inconsistent_local_tr) + best_num_inconsistent_local_tr = num_inconsistent_local_tr; + ++num_steps; done = (num_inconsistent_local_tr == 0); if (time_limit != 0 && t.elapsed() > time_limit) @@ -1268,6 +1276,9 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { + if (tr.is_infinite(*it_c)) // Don't check infinite cells + continue; + //***************************************************************************** // STRATEGY 1: perturb all the points of the first inconsistent simplex //***************************************************************************** From 7c1978e42592bb724840f75ece33280502bce46b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:06:51 +0100 Subject: [PATCH 196/487] Updated script --- .../Tangential_complex/benchmark_script.txt | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index cf2e5e11f60..f2d7fefd45e 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -1,12 +1,25 @@ -#Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY TIME_LIMIT NUM_ITERATIONS -#data/SO3_10000.txt - - - 0 9 3 0.05 60 1 +#--------------------------------------------------------------------------------------------------------------------------------------------------------- +# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY FIX_TIME_LIMIT NUM_ITERATIONS +#--------------------------------------------------------------------------------------------------------------------------------------------------------- -############### Generated point sets ################### -#generate_sphere_d 3 - - 30000 3 2 0.05 60 1 -#generate_moment_curve 0 1 - 30000 6 1 0.05 60 1 -#generate_plane - - - 30000 3 2 0.05 60 1 -#generate_sphere_d 3 - - 30000 3 2 0.05 60 1 -#generate_sphere_d 3 - - 1000 6 5 0.05 60 1 -generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 -generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 -generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file +#------------------------------------------------------------------ From files --------------------------------------------------------------------------- +data/SO3_10000.txt - - - 0 9 3 0.05 60 1 +data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 60 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 60 1 +data/Cy8.txt - - - 0 24 2 0.1 60 1 +data/Kl.txt - - - 0 5 2 0.05 60 1 +data/S3.txt - - - 0 4 3 0.05 60 1 +data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 +data/fandisk.txt - - - 0 3 2 0.001 60 1 + + +#----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ +generate_sphere_d 3 - - 30000 2 1 0.05 60 1 +generate_sphere_d 3 - - 30000 3 2 0.05 60 1 +generate_sphere_d 3 - - 30000 4 3 0.05 60 1 +generate_plane - - - 30000 3 2 0.05 60 1 +generate_moment_curve 0 1 - 30000 6 1 0.05 60 1 +generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 +generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 +generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file From 69b9e2b4429aa1acf41b11f217196c3cef45eb95 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:19:33 +0100 Subject: [PATCH 197/487] Make "sparsity" a parameter --- .../Tangential_complex/benchmark_tc.cpp | 2 +- .../include/CGAL/Tangential_complex.h | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 28fb56d5ae4..f33c1ab443d 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -153,7 +153,7 @@ void make_tc(std::vector &points, int intrinsic_dim, CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); - TC tc(points.begin(), points.end(), intrinsic_dim, k); + TC tc(points.begin(), points.end(), sparsity, intrinsic_dim, k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c2ce1049c88..fa8d91fe235 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,8 +23,6 @@ #define TANGENTIAL_COMPLEX_H #include -const double HALF_SPARSITY = 0.5*INPUT_SPARSITY; -const double SQ_HALF_SPARSITY = HALF_SPARSITY*HALF_SPARSITY; #include #include @@ -186,13 +184,15 @@ public: /// Constructor for a range of points template Tangential_complex(InputIterator first, InputIterator last, - int intrinsic_dimension, + double sparsity, int intrinsic_dimension, const Kernel &k = Kernel()) : m_k(k), m_intrinsic_dimension(intrinsic_dimension), + m_half_sparsity(0.5*sparsity), + m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), + m_ambiant_dim(k.point_dimension_d_object()(*first)), m_points(first, last), - m_points_ds(m_points), - m_ambiant_dim(k.point_dimension_d_object()(*first)) + m_points_ds(m_points) {} /// Destructor @@ -887,7 +887,7 @@ private: if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*SQ_HALF_SPARSITY) // CJTODO: why is "4*" needed? + > *star_sphere_squared_radius + 4*m_sq_half_sparsity) // CJTODO: why is "4*" needed? break; Tr_point proj_pt = project_point_and_compute_weight( @@ -901,7 +901,7 @@ private: // CJTODO TEMP TEST /*if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*SQ_HALF_SPARSITY) + > *star_sphere_squared_radius + 4*m_sq_half_sparsity) std::cout << "ARGGGGGGGH" << std::endl;*/ vh->data() = neighbor_point_idx; @@ -1207,7 +1207,7 @@ private: // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] = rng.get_double(0., SQ_HALF_SPARSITY); + m_weights[point_idx] = rng.get_double(0., m_sq_half_sparsity); #endif // Perturb the position? @@ -1219,7 +1219,7 @@ private: tr_point_on_sphere_generator(m_ambiant_dim, 1); m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); + *tr_point_on_sphere_generator++), m_half_sparsity); # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL const Tr_traits &local_tr_traits = m_triangulations[point_idx].tr().geom_traits(); @@ -1245,7 +1245,7 @@ private: { global_transl = k_transl( global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + k_scaled_vec(tsb[i], m_half_sparsity*coord(local_random_transl, i)) ); } # endif @@ -1618,6 +1618,8 @@ private: private: const Kernel m_k; const int m_intrinsic_dimension; + const double m_half_sparsity; + const double m_sq_half_sparsity; const int m_ambiant_dim; Points m_points; From 32484161a665cdd4d18a76ff39a740f429cf968b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:22:28 +0100 Subject: [PATCH 198/487] Update test according to last changes --- .../test/Tangential_complex/test_tangential_complex.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index f9f359ec450..be393b70f9a 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -91,7 +91,7 @@ int main() std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; - TC tc(points.begin(), points.end(), INTRINSIC_DIMENSION, k); + TC tc(points.begin(), points.end(), INPUT_SPARSITY, INTRINSIC_DIMENSION, k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); @@ -115,8 +115,11 @@ int main() t.reset(); unsigned int num_fix_steps; - CGAL::Fix_inconsistencies_status fix_ret = - tc.fix_inconsistencies(num_fix_steps, 3000.); + std::size_t initial_num_inconsistent_local_tr; + std::size_t best_num_inconsistent_local_tr; + CGAL::Fix_inconsistencies_status fix_ret = tc.fix_inconsistencies( + num_fix_steps, initial_num_inconsistent_local_tr, + best_num_inconsistent_local_tr, 3000.); double fix_time = t.elapsed(); t.reset(); double export_after_time = -1.; From 40981e372d538d4c439176466e960f34e9934209 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:37:26 +0100 Subject: [PATCH 199/487] INPUT_SPARSITY constant is for test only --- .../Tangential_complex/benchmark_script.txt | 18 +++++++++--------- .../Tangential_complex/benchmark_tc.cpp | 3 +-- .../include/CGAL/Tangential_complex/config.h | 1 - .../test_tangential_complex.cpp | 3 +++ .../test/Tangential_complex/test_utilities.h | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index f2d7fefd45e..01831bfcad4 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -3,23 +3,23 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- #------------------------------------------------------------------ From files --------------------------------------------------------------------------- -data/SO3_10000.txt - - - 0 9 3 0.05 60 1 -data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.05 60 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 #data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 60 1 #data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 60 1 -data/Cy8.txt - - - 0 24 2 0.1 60 1 -data/Kl.txt - - - 0 5 2 0.05 60 1 -data/S3.txt - - - 0 4 3 0.05 60 1 +#data/Cy8.txt - - - 0 24 2 0.1 60 1 +#data/Kl.txt - - - 0 5 2 0.05 60 1 +#data/S3.txt - - - 0 4 3 0.05 60 1 data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 data/fandisk.txt - - - 0 3 2 0.001 60 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ -generate_sphere_d 3 - - 30000 2 1 0.05 60 1 -generate_sphere_d 3 - - 30000 3 2 0.05 60 1 +generate_sphere_d 3 - - 30000 2 1 0.005 60 1 +generate_sphere_d 3 - - 30000 3 2 0.005 60 1 generate_sphere_d 3 - - 30000 4 3 0.05 60 1 -generate_plane - - - 30000 3 2 0.05 60 1 -generate_moment_curve 0 1 - 30000 6 1 0.05 60 1 +generate_plane - - - 30000 3 2 0.005 60 1 +generate_moment_curve 0 1 - 30000 6 1 0.005 60 1 generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index f33c1ab443d..aaec0eccaeb 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -144,8 +144,7 @@ void make_tc(std::vector &points, int intrinsic_dim, if (sparsity != 0.) { std::size_t num_points_before = points.size(); - points = sparsify_point_set( - k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + points = sparsify_point_set(k, points, sparsity*sparsity); std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 09abb486a95..4e9b096cd55 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -62,6 +62,5 @@ //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 30; -const double INPUT_SPARSITY = 0.05; #endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index be393b70f9a..92588529562 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -21,11 +21,14 @@ # include #endif +//=============== Constants ================= +const double INPUT_SPARSITY = 0.05; #ifdef _DEBUG const int NUM_POINTS = 50; #else const int NUM_POINTS = 30000; #endif +//=========================================== int main() { diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 4e05725c991..1eb2e3ad57d 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -49,7 +49,7 @@ public: // 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)) + FT sparsity = FT(0.05*0.05)) : m_points(points), m_sparsity(sparsity), m_points_ds(NULL) {} From 0e41484487b572a7b54425c68c8f7c8ba48d41f0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 18:16:15 +0100 Subject: [PATCH 200/487] Added Final_num_inconsistent_local_tr + bugfix --- .../Tangential_complex/benchmark_tc.cpp | 22 ++++++++++++++++--- .../include/CGAL/Tangential_complex.h | 9 ++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index aaec0eccaeb..57feead3808 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -88,6 +88,7 @@ protected: subelements.push_back("Num_points"); subelements.push_back("Initial_num_inconsistent_local_tr"); subelements.push_back("Best_num_inconsistent_local_tr"); + subelements.push_back("Final_num_inconsistent_local_tr"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); subelements.push_back("Fix_successful"); @@ -128,6 +129,17 @@ void make_tc(std::vector &points, int intrinsic_dim, Kernel k; Wall_clock_timer t; + std::string input_name_stripped(input_name); + size_t slash_index = input_name_stripped.find_last_of('/'); + if (slash_index == std::string::npos) + slash_index = input_name_stripped.find_last_of('\\'); + if (slash_index == std::string::npos) + slash_index = 0; + else + ++slash_index; + input_name_stripped = input_name_stripped.substr( + slash_index, input_name_stripped.find_last_of('.') - slash_index); + int ambient_dim = k.point_dimension_d_object()(*points.begin()); #ifdef CGAL_TC_PROFILING @@ -166,7 +178,7 @@ void make_tc(std::vector &points, int intrinsic_dim, { t.reset(); std::stringstream output_filename; - output_filename << "output/" << input_name << "_" << intrinsic_dim + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); @@ -178,22 +190,26 @@ void make_tc(std::vector &points, int intrinsic_dim, unsigned int num_fix_steps; std::size_t initial_num_inconsistent_local_tr; std::size_t best_num_inconsistent_local_tr; + std::size_t final_num_inconsistent_local_tr; CGAL::Fix_inconsistencies_status fix_ret = tc.fix_inconsistencies( num_fix_steps, initial_num_inconsistent_local_tr, - best_num_inconsistent_local_tr, time_limit_for_fix); + best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, + time_limit_for_fix); double fix_time = t.elapsed(); t.reset(); CGAL_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", initial_num_inconsistent_local_tr); CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", best_num_inconsistent_local_tr); + CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", + final_num_inconsistent_local_tr); double export_after_time = -1.; if (intrinsic_dim <= 3) { t.reset(); std::stringstream output_filename; - output_filename << "output/" << input_name << "_" << intrinsic_dim + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fa8d91fe235..3922b17800f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -338,8 +338,11 @@ public: // time_limit in seconds Fix_inconsistencies_status fix_inconsistencies( - unsigned int &num_steps, std::size_t &initial_num_inconsistent_local_tr, - std::size_t &best_num_inconsistent_local_tr, double time_limit = 0.) + unsigned int &num_steps, + std::size_t &initial_num_inconsistent_local_tr, + std::size_t &best_num_inconsistent_local_tr, + std::size_t &final_num_inconsistent_local_tr, + double time_limit = 0.) { Wall_clock_timer t; @@ -462,6 +465,8 @@ public: if (num_inconsistent_local_tr < best_num_inconsistent_local_tr) best_num_inconsistent_local_tr = num_inconsistent_local_tr; + final_num_inconsistent_local_tr = num_inconsistent_local_tr; + ++num_steps; done = (num_inconsistent_local_tr == 0); if (time_limit != 0 && t.elapsed() > time_limit) From 712ba3fc11a5e7c54ffa0ae2476f5f6366a0fb94 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 18:18:33 +0100 Subject: [PATCH 201/487] Updated script --- .../Tangential_complex/benchmark_script.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 01831bfcad4..a8b37db1bbb 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -3,15 +3,15 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- #------------------------------------------------------------------ From files --------------------------------------------------------------------------- -#data/SO3_10000.txt - - - 0 9 3 0.05 60 1 -#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 +data/SO3_10000.txt - - - 0 9 3 0.05 60 1 +data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 #data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 60 1 #data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 60 1 -#data/Cy8.txt - - - 0 24 2 0.1 60 1 -#data/Kl.txt - - - 0 5 2 0.05 60 1 -#data/S3.txt - - - 0 4 3 0.05 60 1 +data/Cy8.txt - - - 0 24 2 0.1 60 1 +data/Kl.txt - - - 0 5 2 0.05 60 1 +data/S3.txt - - - 0 4 3 0.05 60 1 data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 -data/fandisk.txt - - - 0 3 2 0.001 60 1 +data/fandisk.txt - - - 0 3 2 0.01 60 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ From 2cec91f5f5864a04e2bf4d828bbc88a7cba619f3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 18:31:08 +0100 Subject: [PATCH 202/487] Try another technique --- Tangential_complex/include/CGAL/Tangential_complex/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 4e9b096cd55..99700380d61 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -43,8 +43,8 @@ // Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points -//#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) -#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) +#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) +//#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN From 4a588310d9faac9851e48061f628621613789cd4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 2 Feb 2015 10:18:39 +0100 Subject: [PATCH 203/487] Unused variable --- Tangential_complex/include/CGAL/Tangential_complex.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3922b17800f..58501ed0f7c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1426,7 +1426,6 @@ private: neighbors.push_back(nn_it->first); } - CGAL::Random rng; for (std::vector::iterator it = neighbors.begin(); it != neighbors.end() ; ++it) From 6012256fc17b103190b786a0ee2b9d162304c605 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Feb 2015 15:01:41 +0100 Subject: [PATCH 204/487] Updated comment --- Tangential_complex/include/CGAL/Tangential_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 58501ed0f7c..f58170d6e27 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -890,9 +890,10 @@ private: FT neighbor_weight = 0; #endif + // "4*m_sq_half_sparsity" because both points can be perturbed if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*m_sq_half_sparsity) // CJTODO: why is "4*" needed? + > *star_sphere_squared_radius + 4*m_sq_half_sparsity) break; Tr_point proj_pt = project_point_and_compute_weight( From 875a33fef12f6a202836d9e88d9c08b1fb5c7acc Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Feb 2015 18:10:34 +0100 Subject: [PATCH 205/487] Avoid to export duplicate simplices --- .../include/CGAL/Tangential_complex.h | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f58170d6e27..e01778c7c2c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1301,7 +1301,7 @@ private: if (!is_simplex_consistent(c)) { is_inconsistent = true; - + for (std::set::iterator it=c.begin(); it!=c.end(); ++it) perturb(*it); @@ -1516,7 +1516,7 @@ private: typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for ( ; it_tr != it_tr_end ; ++it_tr) + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); @@ -1555,6 +1555,11 @@ private: if (m_intrinsic_dimension == 1) sstr_c << (data*factor + 1) << " "; + // In order to have only one time each simplex, we only keep it + // if the lowest index is the index of the center vertex + if (*c.begin() != idx) + continue; + bool excluded = (excluded_simplices && excluded_simplices->find(c) != excluded_simplices->end()); @@ -1582,16 +1587,27 @@ private: else { os << OFF_simplices_dim << " "; + std::size_t min_index = std::numeric_limits::max(); std::size_t data; + std::stringstream sstr_c; for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) { data = (*it_c)->vertex(i)->data(); - os << data*factor << " "; + if (data < min_index) + min_index = data; + sstr_c << data*factor << " "; } + + // In order to have only one time each simplex, we only keep it + // if the lowest index is the index of the center vertex + if (min_index != idx) + continue; + // See export_vertices_to_off if (m_intrinsic_dimension == 1) - os << (data*factor + 1) << " "; + sstr_c << (data*factor + 1) << " "; + os << sstr_c.str(); ++num_simplices; } From 39524b21ebd2a5f945443e66430544fba9cf5331 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Feb 2015 18:32:23 +0100 Subject: [PATCH 206/487] Fixed debug code (2-sphere normal computation) --- .../include/CGAL/Tangential_complex.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index e01778c7c2c..d1898215b90 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -970,6 +970,8 @@ private: #endif ) const { + //******************************* PCA ************************************* + // Kernel functors typename Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); @@ -987,8 +989,6 @@ private: KNS_range kns_range = m_points_ds.query_ANN( p, NUM_POINTS_FOR_PCA, false); - //******************************* PCA ************************************* - // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); KNS_iterator nn_it = kns_range.begin(); @@ -1030,12 +1030,14 @@ private: return compute_gram_schmidt_basis(ts, m_k); - /* + // CJTODO: this is only for a sphere in R^3 - Vector t1(-p[1] - p[2], p[0], p[0]); - Vector t2(p[1] * t1[2] - p[2] * t1[1], - p[2] * t1[0] - p[0] * t1[2], - p[0] * t1[1] - p[1] * t1[0]); + /*double tt1[3] = {-p[1] - p[2], p[0], p[0]}; + double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], + p[2] * tt1[0] - p[0] * tt1[2], + p[0] * tt1[1] - p[1] * tt1[0]}; + Vector t1(3, &tt1[0], &tt1[3]); + Vector t2(3, &tt2[0], &tt2[3]); // Normalize t1 and t2 typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); From a9c27d8db6bd7047e50254447665470e5e4a0753 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 5 Feb 2015 11:53:28 +0100 Subject: [PATCH 207/487] Added option USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + fix export --- .../Tangential_complex/benchmark_tc.cpp | 12 +++- .../include/CGAL/Tangential_complex.h | 56 +++++++++++++++---- .../include/CGAL/Tangential_complex/config.h | 1 + 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 57feead3808..a1877f69dd5 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -152,6 +152,10 @@ void make_tc(std::vector &points, int intrinsic_dim, #endif CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); + +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + std::vector points_not_sparse = points; +#endif if (sparsity != 0.) { @@ -163,8 +167,14 @@ void make_tc(std::vector &points, int intrinsic_dim, CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); - + +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + TC tc(points.begin(), points.end(), sparsity, intrinsic_dim, + points_not_sparse.begin(), points_not_sparse.end(), k); +#else TC tc(points.begin(), points.end(), sparsity, intrinsic_dim, k); +#endif + double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d1898215b90..9b928710272 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -185,7 +185,11 @@ public: template Tangential_complex(InputIterator first, InputIterator last, double sparsity, int intrinsic_dimension, - const Kernel &k = Kernel()) +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + InputIterator first_for_tse, InputIterator last_for_tse, +#endif + const Kernel &k = Kernel() + ) : m_k(k), m_intrinsic_dimension(intrinsic_dimension), m_half_sparsity(0.5*sparsity), @@ -193,6 +197,10 @@ public: m_ambiant_dim(k.point_dimension_d_object()(*first)), m_points(first, last), m_points_ds(m_points) +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + , m_points_for_tse(first_for_tse, last_for_tse) + , m_points_ds_for_tse(m_points_for_tse) +#endif {} /// Destructor @@ -985,9 +993,15 @@ private: m_k.scalar_product_d_object(); typename Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - - KNS_range kns_range = m_points_ds.query_ANN( + +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + KNS_range kns_range = m_points_ds_for_tse.query_ANN( p, NUM_POINTS_FOR_PCA, false); + const Points &points_for_pca = m_points_for_tse; +#else + KNS_range kns_range = m_points_ds.query_ANN(p, NUM_POINTS_FOR_PCA, false); + const Points &points_for_pca = m_points; +#endif // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); @@ -997,7 +1011,7 @@ private: ++j, ++nn_it) { for (int i = 0 ; i < m_ambiant_dim ; ++i) - mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); + mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -1515,11 +1529,14 @@ private: (m_intrinsic_dimension == 1 ? 3 : m_intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; + std::size_t num_inconsistent_stars = 0; typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { + bool is_star_inconsistent = false; + Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); @@ -1553,13 +1570,18 @@ private: sstr_c << data*factor << " "; c.insert(data); } + + bool is_simpl_consistent = is_simplex_consistent(c); + if (!is_simpl_consistent) + is_star_inconsistent = true; + // See export_vertices_to_off if (m_intrinsic_dimension == 1) sstr_c << (data*factor + 1) << " "; // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != idx) + if (*c.begin() != idx && is_simpl_consistent) continue; bool excluded = @@ -1569,7 +1591,7 @@ private: if (!excluded) { os << OFF_simplices_dim << " " << sstr_c.str() << " "; - if (color_inconsistencies && is_simplex_consistent(c)) + if (color_inconsistencies && is_simpl_consistent) os << color.str(); else { @@ -1615,6 +1637,8 @@ private: os << std::endl; } + if (is_star_inconsistent) + ++num_inconsistent_stars; } #ifdef CGAL_TC_VERBOSE @@ -1623,13 +1647,16 @@ private: << std::endl << "Export to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices in stars (incl. duplicates): " - << num_simplices << std::endl - << " * Number of inconsistent simplices in stars (incl. duplicates): " - << num_inconsistent_simplices << std::endl - << " * Percentage of inconsistencies: " + << " * Total number of simplices: " << num_simplices << std::endl + << " * Number of inconsistent stars: " + << num_inconsistent_stars << " (" + << (m_points.size() > 0 ? + 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)" + << std::endl + << " * Number of inconsistent simplices: " + << num_inconsistent_simplices << " (" << (num_simplices > 0 ? - 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" + 100. * num_inconsistent_simplices / num_simplices : 0.) << "%)" << std::endl << "==========================================================" << std::endl; @@ -1664,6 +1691,11 @@ private: Vectors m_normals; #endif +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + Points m_points_for_tse; + Points_ds m_points_ds_for_tse; +#endif + }; // /class Tangential_complex } // end namespace CGAL diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 99700380d61..871b8fb5ef4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -35,6 +35,7 @@ #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES +#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM // Solving inconsistencies: only perturb the vertex, the simplex or more? //#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY From 0ed94233cb55c0fd726f850cae49706e6d7987ff Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 10 Feb 2015 13:11:23 +0100 Subject: [PATCH 208/487] Add a cache to store stars (uses std::set) --- .../include/CGAL/Tangential_complex.h | 60 +++++++++++++++---- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 9b928710272..ae02c0914e7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -122,6 +122,7 @@ class Tangential_complex typedef std::vector Points; typedef std::vector Weights; + typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; @@ -167,6 +168,13 @@ class Tangential_complex typedef typename std::vector TS_container; typedef typename std::vector Tr_container; typedef typename std::vector Vectors; + + // An Incident_simplex is the list of the verter indices + // except the center vertex + typedef std::set Incident_simplex; + typedef std::vector Star; + typedef std::vector Stars_container; + #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm @@ -221,6 +229,7 @@ public: // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); + m_stars.resize(m_points.size()); #ifdef CGAL_LINKED_WITH_TBB //m_tr_mutexes.resize(m_points.size()); #endif @@ -962,6 +971,34 @@ private: } + + //*************************************************** + // Update the associated star (in m_stars) + //*************************************************** + Star &star = m_stars[i]; + int cur_dim_plus_1 = local_tr.current_dimension() + 1; + star.clear(); + + std::vector incident_cells; + local_tr.incident_full_cells( + center_vertex, std::back_inserter(incident_cells)); + + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + // Will contain all indices except center_vertex + Incident_simplex inc_simplex; + for (int j = 0 ; j < cur_dim_plus_1 ; ++j) + { + std::size_t index = (*it_c)->vertex(j)->data(); + if (index != i) + inc_simplex.insert(index); + } + star.push_back(inc_simplex); + } + // CJTODO DEBUG //std::cerr << "\nChecking topology and geometry..." // << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); @@ -1169,23 +1206,23 @@ private: std::size_t point_idx = *it_point_idx; if (point_idx == std::numeric_limits::max()) continue; - Triangulation const& tr = m_triangulations[point_idx].tr(); - Tr_vertex_handle center_vh = m_triangulations[point_idx].center_vertex(); + Star const& star = m_stars[point_idx]; - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + // What we're looking for is "simplex" \ point_idx + Incident_simplex ic_to_find = simplex; + ic_to_find.erase(point_idx); - typename std::vector::const_iterator it_c = incident_cells.begin(); - typename std::vector::const_iterator it_c_end= incident_cells.end(); // For each cell bool found = false; - for ( ; !found && it_c != it_c_end ; ++it_c) + Star::const_iterator it_inc_simplex = star.begin(); + Star::const_iterator it_inc_simplex_end = star.end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - std::set cell; - for (int i = 0 ; i < cur_dim_plus_1 ; ++i) - cell.insert((*it_c)->vertex(i)->data()); - if (cell == simplex) + if (*it_inc_simplex == ic_to_find) + { found = true; + break; + } } if (!found) @@ -1684,6 +1721,7 @@ private: TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations // and their center vertex + Stars_container m_stars; #ifdef CGAL_LINKED_WITH_TBB //std::vector m_tr_mutexes; #endif From 039af01fe505f07a1bd7b790724a46c8e30cae01 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 10 Feb 2015 16:34:22 +0100 Subject: [PATCH 209/487] Optimize functions thanks to the cache "m_stars" Most calls to incident_full_cells can be avoided --- .../include/CGAL/Tangential_complex.h | 157 ++++++++++-------- .../include/CGAL/Tangential_complex/config.h | 8 +- 2 files changed, 97 insertions(+), 68 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ae02c0914e7..a3a59df54fe 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -518,6 +518,7 @@ public: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); + // CJTODO: use m_stars[...] std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); @@ -970,8 +971,6 @@ private: } } - - //*************************************************** // Update the associated star (in m_stars) //*************************************************** @@ -1262,11 +1261,9 @@ private: void perturb(std::size_t point_idx) { - CGAL::Random rng; - // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] = rng.get_double(0., m_sq_half_sparsity); + m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); #endif // Perturb the position? @@ -1320,50 +1317,46 @@ private: //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif + Star const& star = m_stars[tr_index]; Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); const Tr_traits &local_tr_traits = tr.geom_traits(); int cur_dim = tr.current_dimension(); - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - typename std::vector::const_iterator it_c = - incident_cells.begin(); - typename std::vector::const_iterator it_c_end= - incident_cells.end(); - // For each cell - for ( ; it_c != it_c_end ; ++it_c) + // For each incident simplex + Star::const_iterator it_inc_simplex = star.begin(); + Star::const_iterator it_inc_simplex_end = star.end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - if (tr.is_infinite(*it_c)) // Don't check infinite cells + const Incident_simplex &inc_simplex = *it_inc_simplex; + + // Don't check infinite cells + if (*inc_simplex.rbegin() == std::numeric_limits::max()) continue; + std::set c = inc_simplex; + c.insert(tr_index); // Add the missing index + //***************************************************************************** // STRATEGY 1: perturb all the points of the first inconsistent simplex //***************************************************************************** #ifdef CGAL_TC_PERTURB_THE_SIMPLEX_ONLY - - std::set c; - for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) - { - std::size_t data = (*it_c)->vertex(i)->data(); - c.insert(data); - } - // Inconsistent? if (!is_simplex_consistent(c)) { is_inconsistent = true; - for (std::set::iterator it=c.begin(); it!=c.end(); ++it) + for (std::set::const_iterator it = c.begin(); + it != c.end() ; ++it) + { perturb(*it); + } # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif - // We will try the other cells next time (incident_cells is not - // valid anymore here) + // We will try the other cells next time break; } @@ -1371,7 +1364,7 @@ private: // STRATEGY 2: perturb the center point only //***************************************************************************** #elif defined(CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY) - if (!is_simplex_consistent(*it_c, cur_dim)) + if (!is_simplex_consistent(c)) { is_inconsistent = true; @@ -1389,8 +1382,7 @@ private: refresh_tangential_complex(); # endif - // We will try the other cells next time (incident_cells is not - // valid anymore here) + // We will try the other cells next time break; } @@ -1400,43 +1392,68 @@ private: #elif defined(CGAL_TC_PERTURB_THE_1_STAR) // Inconsistent? - if (!is_simplex_consistent(*it_c, cur_dim)) + if (!is_simplex_consistent(c)) { is_inconsistent = true; - std::set c; + std::set the_1_star; - typename std::vector::const_iterator it_c2 = - incident_cells.begin(); - // For each cell - for ( ; it_c2 != it_c_end ; ++it_c2) + Star::const_iterator it_inc_simplex = star.begin(); + Star::const_iterator it_inc_simplex_end = star.end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) - { - std::size_t data = (*it_c2)->vertex(i)->data(); - c.insert(data); - } + the_1_star.insert(it_inc_simplex->begin(), it_inc_simplex ->end()); } - for (std::set::iterator it=c.begin(); it!=c.end(); ++it) + for (std::set::iterator it = the_1_star.begin() ; + it != the_1_star.end() ; ++it) + { perturb(*it); + } # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif - // We will try the other cells next time (incident_cells is not - // valid anymore here) + // We will try the other cells next time break; } +//***************************************************************************** +// STRATEGY 4: perturb one random point of the simplex +//***************************************************************************** +#else + // Inconsistent? + if (!is_simplex_consistent(c)) + { + is_inconsistent = true; + int rnd = m_random_generator.get_int(0, static_cast(c.size())); + if (rnd == 0) + perturb(tr_index); + else + { + std::set::const_iterator it_idx = c.begin(); + std::advance(it_idx, rnd - 1); + perturb(*it_idx); + } + +# if !defined(CGAL_TC_GLOBAL_REFRESH) + refresh_tangential_complex(); +# endif + + // We will try the other cells next time + break; + } + +#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY + //***************************************************************************** // STRATEGY 4: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points (to the power center of first the inconsistent cell) //***************************************************************************** -#else +/*#else // Inconsistent? - if (!is_simplex_consistent(*it_c, cur_dim)) + if (!is_simplex_consistent(c)) { is_inconsistent = true; @@ -1444,8 +1461,13 @@ private: // closest points std::vector simplex_pts; - for (int i = 0 ; i < cur_dim + 1 ; ++i) - simplex_pts.push_back((*it_c)->vertex(i)->point()); + + Incident_simplex::const_iterator it_point_idx = c.begin(); + Incident_simplex::const_iterator it_point_idx_end = c.end(); + // For each point p of the simplex, we parse the incidents cells of p + // and we check if "simplex" is among them + for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) + simplex_pts.push_back(m_points[*it_point_idx]); //typename Tr_traits::Power_center_d power_center = // local_tr_traits.power_center_d_object(); // CJTODO @@ -1491,12 +1513,11 @@ private: refresh_tangential_complex(); # endif - // We will try the other cells next time (incident_cells is not - // valid anymore here) + // We will try the other cells next time break; } -#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY +#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY*/ } return is_inconsistent; @@ -1584,28 +1605,29 @@ private: std::stringstream color; //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; color << 128 << " " << 128 << " " << 128; - - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - typename std::vector::const_iterator it_c = incident_cells.begin(); - typename std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell - for ( ; it_c != it_c_end ; ++it_c) + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - if (tr.is_infinite(*it_c)) // Don't export infinite cells + // Don't export infinite cells + if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; + + std::set c = *it_inc_simplex; + c.insert(idx); if (color_inconsistencies || excluded_simplices) { - std::set c; std::stringstream sstr_c; std::size_t data; - for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) + + std::set::const_iterator it_point_idx = c.begin(); + for ( ; it_point_idx != c.end() ; ++it_point_idx) { - data = (*it_c)->vertex(i)->data(); + data = *it_point_idx; sstr_c << data*factor << " "; - c.insert(data); } bool is_simpl_consistent = is_simplex_consistent(c); @@ -1651,11 +1673,11 @@ private: std::size_t min_index = std::numeric_limits::max(); std::size_t data; std::stringstream sstr_c; - for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) + std::set::const_iterator it_point_idx = c.begin(); + min_index = *it_point_idx; + for ( ; it_point_idx != c.end() ; ++it_point_idx) { - data = (*it_c)->vertex(i)->data(); - if (data < min_index) - min_index = data; + data = *it_point_idx; sstr_c << data*factor << " "; } @@ -1734,6 +1756,9 @@ private: Points_ds m_points_ds_for_tse; #endif + + CGAL::Random m_random_generator; + }; // /class Tangential_complex } // end namespace CGAL diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 871b8fb5ef4..0c38e13ad8b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -35,17 +35,21 @@ #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +//#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM // Solving inconsistencies: only perturb the vertex, the simplex or more? //#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY //#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY //#define CGAL_TC_PERTURB_THE_1_STAR +// Otherwise, perturb one random point of the simplex + +/* // Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points #define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) //#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) +*/ //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN @@ -62,6 +66,6 @@ //#define CGAL_TC_PERTURB_WEIGHT //========================= Parameters ======================================== -const std::size_t NUM_POINTS_FOR_PCA = 30; +const std::size_t NUM_POINTS_FOR_PCA = 20; #endif // CGAL_TC_CONFIG_H From c73b9c3316e50b6f256e4fb1ddab9465f2e80ef7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 10 Feb 2015 19:33:07 +0100 Subject: [PATCH 210/487] Added the ability to perturb tangent spaces + fix Compute_tangent_triangulation constructor --- .../include/CGAL/Tangential_complex.h | 45 +++++++++++++++++-- .../include/CGAL/Tangential_complex/config.h | 1 + 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index a3a59df54fe..55fb8e26167 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -241,6 +241,9 @@ public: m_translations.resize(m_points.size(), m_k.construct_vector_d_object()(m_ambiant_dim)); #endif +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + m_perturb_tangent_space.resize(m_points.size(), false); +#endif #ifdef CGAL_TC_EXPORT_NORMALS m_normals.resize(m_points.size(), m_k.construct_vector_d_object()(m_ambiant_dim)); @@ -800,7 +803,9 @@ private: // Constructor Compute_tangent_triangulation(const Compute_tangent_triangulation &ctt) - : m_tc(ctt.m_tc) + : m_tc(ctt.m_tc), + m_tangent_spaces_are_already_computed( + ctt.m_tangent_spaces_are_already_computed) {} // operator() @@ -858,6 +863,17 @@ private: m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif } +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + else if (m_perturb_tangent_space[i]) + { +#ifdef CGAL_TC_EXPORT_NORMALS + m_tangent_spaces[i] = compute_tangent_space(center_pt,&m_normals[i],true); +#else + m_tangent_spaces[i] = compute_tangent_space(center_pt, true); +#endif + m_perturb_tangent_space[i] = false; + } +#endif //*************************************************** // Build a minimal triangulation in the tangent space @@ -1011,6 +1027,9 @@ private: Tangent_space_basis compute_tangent_space(const Point &p #ifdef CGAL_TC_EXPORT_NORMALS , Vector *p_normal +#endif +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + , bool perturb = false #endif ) const { @@ -1029,6 +1048,8 @@ private: m_k.scalar_product_d_object(); typename Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); + //typename Kernel::Translated_point_d transl = + // m_k.translated_point_d_object(); #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM KNS_range kns_range = m_points_ds_for_tse.query_ANN( @@ -1047,7 +1068,15 @@ private: ++j, ++nn_it) { for (int i = 0 ; i < m_ambiant_dim ; ++i) - mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i)); + { + //const Point p = transl( + // m_points[nn_it->first], m_translations[nn_it->first]); + mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + if (perturb) + mat_points(j, i) += m_random_generator.get_double(-0.3, 0.3); +#endif + } } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -1203,8 +1232,10 @@ private: for ( ; it_point_idx != simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; + // Don't check infinite simplices if (point_idx == std::numeric_limits::max()) continue; + Star const& star = m_stars[point_idx]; // What we're looking for is "simplex" \ point_idx @@ -1265,6 +1296,10 @@ private: #ifdef CGAL_TC_PERTURB_WEIGHT m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); #endif + +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + m_perturb_tangent_space[point_idx] = true; +#endif // Perturb the position? #ifdef CGAL_TC_PERTURB_POSITION @@ -1738,6 +1773,9 @@ private: #ifdef CGAL_TC_PERTURB_POSITION Vectors m_translations; #endif +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + std::vector m_perturb_tangent_space; +#endif Points_ds m_points_ds; TS_container m_tangent_spaces; @@ -1756,8 +1794,7 @@ private: Points_ds m_points_ds_for_tse; #endif - - CGAL::Random m_random_generator; + mutable CGAL::Random m_random_generator; }; // /class Tangential_complex diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 0c38e13ad8b..a5ed583a95d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -64,6 +64,7 @@ # define CGAL_TC_PERTURB_POSITION_TANGENTIAL // default //# define CGAL_TC_PERTURB_POSITION_GLOBAL //#define CGAL_TC_PERTURB_WEIGHT +//#define CGAL_TC_PERTURB_TANGENT_SPACE //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 20; From 643123afdac5e43122a4ad3f02fe5b569f64f83f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 11:47:08 +0100 Subject: [PATCH 211/487] Update test (new param) --- .../test/Tangential_complex/test_tangential_complex.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 92588529562..69f6f54f02e 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -120,9 +120,10 @@ int main() unsigned int num_fix_steps; std::size_t initial_num_inconsistent_local_tr; std::size_t best_num_inconsistent_local_tr; + std::size_t final_num_inconsistent_local_tr; CGAL::Fix_inconsistencies_status fix_ret = tc.fix_inconsistencies( num_fix_steps, initial_num_inconsistent_local_tr, - best_num_inconsistent_local_tr, 3000.); + best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, 1000.); double fix_time = t.elapsed(); t.reset(); double export_after_time = -1.; From f4496dfd7efb6f38a649a316bed6b97cc5316d42 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 11:52:07 +0100 Subject: [PATCH 212/487] Updated script --- .../Tangential_complex/benchmark_script.txt | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index a8b37db1bbb..ffcaec285e8 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -2,24 +2,33 @@ # Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- -#------------------------------------------------------------------ From files --------------------------------------------------------------------------- -data/SO3_10000.txt - - - 0 9 3 0.05 60 1 -data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 -#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 60 1 -#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 60 1 -data/Cy8.txt - - - 0 24 2 0.1 60 1 -data/Kl.txt - - - 0 5 2 0.05 60 1 -data/S3.txt - - - 0 4 3 0.05 60 1 -data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 -data/fandisk.txt - - - 0 3 2 0.01 60 1 +#---------------------------------------------------------- Very small cases for Debug mode ------------------------------------------------------------- +#generate_sphere_d 3 - - 20 3 2 0.05 3000 1 +#generate_klein_bottle_4D 4 3 - 20 4 2 1.5 3000 1 +#------------------------------------------------------------------ From files --------------------------------------------------------------------------- +#data/SO3_50000.txt - - - 0 9 3 0.2 3000 1 +data/SO3_10000.txt - - - 0 9 3 0.05 3000 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 3000 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 3000 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 3000 1 +#data/Cy8.txt - - - 0 24 2 0.1 3000 1 +#data/Kl.txt - - - 0 5 2 0.05 3000 1 +#data/S3.txt - - - 0 4 3 0.05 3000 1 +#data/buddha_100kv.txt - - - 0 3 2 0.005 3000 1 +#data/fandisk.txt - - - 0 3 2 0.01 3000 1 +#data/fertility.txt - - - 0 3 2 0.1 600 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ -generate_sphere_d 3 - - 30000 2 1 0.005 60 1 -generate_sphere_d 3 - - 30000 3 2 0.005 60 1 -generate_sphere_d 3 - - 30000 4 3 0.05 60 1 -generate_plane - - - 30000 3 2 0.005 60 1 -generate_moment_curve 0 1 - 30000 6 1 0.005 60 1 -generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 -generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 -generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file +#generate_sphere_d 3 - - 4 3 2 0.05 3000 1 +#generate_sphere_d 3 - - 30000 2 1 0.005 3000 1 +#generate_sphere_d 3 - - 30000 3 2 0.005 3000 1 +#generate_sphere_d 3 - - 30000 4 3 0.05 3000 1 +#generate_plane - - - 30000 3 2 0.005 3000 1 +#generate_moment_curve 0 1 - 30000 6 1 0.005 3000 1 +#generate_klein_bottle_4D 4 3 - 10000 4 2 1.5 3000 1 +#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 3000 1 + +#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------- +# TC: 5.55 / 1st fix step : 2.7 +data/fertility.txt - - - 0 3 2 0.1 600 1 \ No newline at end of file From 4035a51cf2a96d1e501afd1df863388246ca0cfb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 11:55:25 +0100 Subject: [PATCH 213/487] Temporary debug code --- Triangulation/include/CGAL/Triangulation_data_structure.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 94818cc4627..ef10428a5c3 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -664,6 +664,9 @@ Triangulation_data_structure { // CGAL_expensive_precondition(is_vertex(v)); CGAL_precondition(Vertex_handle() != v); + CGAL_precondition(v->full_cell()->has_vertex(v)); + if (!v->full_cell()->has_vertex(v)) // CJTODO TEMP + std::cout << "ERROR: incident_full_cells !v->full_cell()->has_vertex(v). Is the point cloud sparse enough?"; Face f(v->full_cell()); f.set_index(0, v->full_cell()->index(v)); return incident_full_cells(f, out); From d810bd58ee75ac42780dca6f0905d3571c032b47 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 15:56:43 +0100 Subject: [PATCH 214/487] Update number_of_inconsistent_simplices to use cache "m_stars" --- .../include/CGAL/Tangential_complex.h | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 55fb8e26167..f2b2c2dbfb8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -457,7 +457,7 @@ public: << " - Num inconsistent simplices in stars (incl. duplicates): " << stats_after.second << std::endl << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_before.first << "%" + << 100. * stats_after.second / stats_after.first << "%" << std::endl << "==========================================================" << std::endl; @@ -516,27 +516,26 @@ public: typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for ( ; it_tr != it_tr_end ; ++it_tr) + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - // CJTODO: use m_stars[...] - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - typename std::vector::const_iterator it_c = - incident_cells.begin(); - typename std::vector::const_iterator it_c_end = - incident_cells.end(); // For each cell - for ( ; it_c != it_c_end ; ++it_c) + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - if (tr.is_infinite(*it_c)) // Don't check infinite cells + // Don't export infinite cells + if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; + + std::set c = *it_inc_simplex; + c.insert(idx); // Add the missing index - if (!is_simplex_consistent(*it_c, tr.current_dimension())) + if (!is_simplex_consistent(c)) ++num_inconsistent_simplices; + ++num_simplices; } } From ed7fb72f117c310720c9f1dc5cd6017bbd8cca8e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 16:00:06 +0100 Subject: [PATCH 215/487] Added "unproject_point" + fixed export_simplices_to_off (multiple dimensions) --- .../include/CGAL/Tangential_complex.h | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f2b2c2dbfb8..28b35aef12f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1003,14 +1003,14 @@ private: for ( ; it_c != it_c_end ; ++it_c) { // Will contain all indices except center_vertex - Incident_simplex inc_simplex; + Incident_simplex incident_simplex; for (int j = 0 ; j < cur_dim_plus_1 ; ++j) { std::size_t index = (*it_c)->vertex(j)->data(); if (index != i) - inc_simplex.insert(index); + incident_simplex.insert(index); } - star.push_back(inc_simplex); + star.push_back(incident_simplex); } // CJTODO DEBUG @@ -1142,6 +1142,28 @@ private: */ } + Point unproject_point(const Tr_point &p, const Point &origin, + const Tangent_space_basis &tsb, + const Tr_traits &tr_traits) + { + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + tr_traits.compute_coordinate_d_object(); + + Point global_point = origin; + for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + { + global_point = k_transl( + global_point, + k_scaled_vec(tsb[i], coord(p, i))); + } + + return global_point; + } + // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p Tr_bare_point project_point(const Point &p, const Point &origin, @@ -1362,13 +1384,13 @@ private: Star::const_iterator it_inc_simplex_end = star.end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - const Incident_simplex &inc_simplex = *it_inc_simplex; + const Incident_simplex &incident_simplex = *it_inc_simplex; // Don't check infinite cells - if (*inc_simplex.rbegin() == std::numeric_limits::max()) + if (*incident_simplex.rbegin() == std::numeric_limits::max()) continue; - std::set c = inc_simplex; + std::set c = incident_simplex; c.insert(tr_index); // Add the missing index //***************************************************************************** @@ -1617,8 +1639,6 @@ private: // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) int factor = (m_intrinsic_dimension == 1 ? 2 : 1); - int OFF_simplices_dim = - (m_intrinsic_dimension == 1 ? 3 : m_intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; std::size_t num_inconsistent_stars = 0; @@ -1651,6 +1671,7 @@ private: std::set c = *it_inc_simplex; c.insert(idx); + std::size_t num_vertices = c.size(); if (color_inconsistencies || excluded_simplices) { @@ -1670,7 +1691,10 @@ private: // See export_vertices_to_off if (m_intrinsic_dimension == 1) + { sstr_c << (data*factor + 1) << " "; + ++num_vertices; + } // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex @@ -1683,7 +1707,7 @@ private: if (!excluded) { - os << OFF_simplices_dim << " " << sstr_c.str() << " "; + os << num_vertices << " " << sstr_c.str() << " "; if (color_inconsistencies && is_simpl_consistent) os << color.str(); else @@ -1695,7 +1719,7 @@ private: } else if (show_excluded_vertices_in_color) { - os << OFF_simplices_dim << " " + os << num_vertices << " " << sstr_c.str() << " " << "0 0 255"; ++num_simplices; @@ -1703,7 +1727,6 @@ private: } else { - os << OFF_simplices_dim << " "; std::size_t min_index = std::numeric_limits::max(); std::size_t data; std::stringstream sstr_c; @@ -1722,9 +1745,12 @@ private: // See export_vertices_to_off if (m_intrinsic_dimension == 1) + { sstr_c << (data*factor + 1) << " "; + ++num_vertices; + } - os << sstr_c.str(); + os << num_vertices << " " << sstr_c.str(); ++num_simplices; } From 7d928b4489782a2f305076a080c222631f00dbf8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 16:17:46 +0100 Subject: [PATCH 216/487] Re-added the ability to perturb the k + 1 + m closest points --- .../include/CGAL/Tangential_complex.h | 95 +++++++++---------- .../include/CGAL/Tangential_complex/config.h | 8 +- 2 files changed, 50 insertions(+), 53 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 28b35aef12f..fc20415870f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1475,39 +1475,12 @@ private: break; } -//***************************************************************************** -// STRATEGY 4: perturb one random point of the simplex -//***************************************************************************** -#else - // Inconsistent? - if (!is_simplex_consistent(c)) - { - is_inconsistent = true; - int rnd = m_random_generator.get_int(0, static_cast(c.size())); - if (rnd == 0) - perturb(tr_index); - else - { - std::set::const_iterator it_idx = c.begin(); - std::advance(it_idx, rnd - 1); - perturb(*it_idx); - } - -# if !defined(CGAL_TC_GLOBAL_REFRESH) - refresh_tangential_complex(); -# endif - - // We will try the other cells next time - break; - } - -#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY - //***************************************************************************** // STRATEGY 4: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points (to the power center of first the inconsistent cell) //***************************************************************************** -/*#else +#elif defined(CGAL_TC_PERTURB_N_CLOSEST_POINTS) + // Inconsistent? if (!is_simplex_consistent(c)) { @@ -1517,35 +1490,36 @@ private: // closest points std::vector simplex_pts; + simplex_pts.reserve(c.size()); Incident_simplex::const_iterator it_point_idx = c.begin(); Incident_simplex::const_iterator it_point_idx_end = c.end(); - // For each point p of the simplex, we parse the incidents cells of p - // and we check if "simplex" is among them + // For each point p of the simplex, we reproject it onto the tangent + // space. Could be optimized since it's already been computed before. for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) - simplex_pts.push_back(m_points[*it_point_idx]); + { +#ifdef CGAL_TC_PERTURB_WEIGHT + FT w = m_weights[*it_point_idx]; +#else + FT w = 0; +#endif + simplex_pts.push_back(project_point_and_compute_weight( + m_points[*it_point_idx], w, + m_points[tr_index], m_tangent_spaces[tr_index], + local_tr_traits)); + } //typename Tr_traits::Power_center_d power_center = // local_tr_traits.power_center_d_object(); // CJTODO typename Get_functor::type power_center(local_tr_traits); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); - - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - m_k.scaled_vector_d_object(); - - Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); - Point global_center = m_points[tr_index]; - const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; - for (int i = 0 ; i < m_intrinsic_dimension ; ++i) - { - global_center = k_transl( - global_center, - k_scaled_vec(tsb[i], coord(local_center, i))); - } + Point global_center = unproject_point( + power_center(simplex_pts.begin(), simplex_pts.end()), + m_points[tr_index], + m_tangent_spaces[tr_index], + local_tr_traits); KNS_range kns_range = m_points_ds.query_ANN( global_center, @@ -1572,8 +1546,33 @@ private: // We will try the other cells next time break; } +//***************************************************************************** +// STRATEGY 5: perturb one random point of the simplex +//***************************************************************************** +#else + // Inconsistent? + if (!is_simplex_consistent(c)) + { + is_inconsistent = true; + int rnd = m_random_generator.get_int(0, static_cast(c.size())); + if (rnd == 0) + perturb(tr_index); + else + { + std::set::const_iterator it_idx = c.begin(); + std::advance(it_idx, rnd - 1); + perturb(*it_idx); + } -#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY*/ +# if !defined(CGAL_TC_GLOBAL_REFRESH) + refresh_tangential_complex(); +# endif + + // We will try the other cells next time + break; + } + +#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY } return is_inconsistent; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index a5ed583a95d..f9339340dbe 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -41,15 +41,13 @@ //#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY //#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY //#define CGAL_TC_PERTURB_THE_1_STAR +#define CGAL_TC_PERTURB_N_CLOSEST_POINTS // perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS closest points // Otherwise, perturb one random point of the simplex - -/* -// Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS -// closest points +// Only used if CGAL_TC_PERTURB_N_CLOSEST_POINTS is defined #define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) //#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) -*/ + //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN From e5b56dc50447cb62a84ccdb9dc5bda4661727c53 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 12 Feb 2015 00:09:55 +0100 Subject: [PATCH 217/487] Added a new way to fix inconsistencies + simpler export_simplices_to_off Remaining inconsistencies are fixed by adding higher-dim simplices. Future work: collapse them. --- .../Tangential_complex/benchmark_tc.cpp | 7 +- .../include/CGAL/Tangential_complex.h | 400 ++++++++++++++---- .../test_tangential_complex.cpp | 7 +- 3 files changed, 322 insertions(+), 92 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index a1877f69dd5..ed55aa637db 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -180,8 +180,7 @@ void make_tc(std::vector &points, int intrinsic_dim, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - std::set > incorrect_simplices; - //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); double export_before_time = -1.; if (intrinsic_dim <= 3) @@ -191,7 +190,7 @@ void make_tc(std::vector &points, int intrinsic_dim, output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); + tc.export_to_off(off_stream, true); export_before_time = t.elapsed(); t.reset(); } @@ -222,7 +221,7 @@ void make_tc(std::vector &points, int intrinsic_dim, output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); + tc.export_to_off(off_stream, true); export_after_time = t.elapsed(); t.reset(); } /*else diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fc20415870f..52592f7a0bc 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -489,11 +489,13 @@ public: ++num_steps; done = (num_inconsistent_local_tr == 0); - if (time_limit != 0 && t.elapsed() > time_limit) + if (!done && time_limit != 0 && t.elapsed() > time_limit) { #ifdef CGAL_TC_VERBOSE std::cerr << "Time limit reached." << std::endl; #endif + check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); // CJTODO: make it optional? + return TIME_LIMIT_REACHED; } } @@ -561,10 +563,7 @@ public: } std::ostream &export_to_off( - std::ostream & os, - bool color_inconsistencies = false, - std::set > const* excluded_simplices = NULL, - bool show_excluded_vertices_in_color = false) + std::ostream & os, bool color_inconsistencies = false) { if (m_points.empty()) return os; @@ -600,8 +599,7 @@ public: std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); export_simplices_to_off( - output, num_simplices, color_inconsistencies, - excluded_simplices, show_excluded_vertices_in_color); + output, num_simplices, color_inconsistencies); #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; @@ -1629,15 +1627,245 @@ private: return os; } + void insert_higher_dim_simplex_into_star( + std::size_t index, + const std::set &simplex) + { + Incident_simplex incident_simplex = simplex; + incident_simplex.erase(index); // Remove the center index + + Star &star = m_stars[index]; + + std::set::const_iterator it_point_idx = simplex.begin(); + std::set::const_iterator it_point_idx_end = simplex.end(); + for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) + { + // Skip center index + if (*it_point_idx == index) + continue; + + // Temporarily remove this index + incident_simplex.erase(*it_point_idx); + // Erase incident_simplex from star + star.erase(std::remove(star.begin(), star.end(), incident_simplex), + star.end()); + incident_simplex.insert(*it_point_idx); + } + + star.push_back(incident_simplex); + } + + // Solves one inconsistency + // "inconsistent_simplex" must contain p_idx and q_idx + void solve_inconsistency_by_adding_higher_dimensional_simplices( + std::size_t p_idx, std::size_t q_idx, + const std::set &inconsistent_simplex) + { + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + + const Tr_traits &q_tr_traits = m_triangulations[q_idx].tr().geom_traits(); + /*typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object();*/ // CJTODO + typename Get_functor::type tr_power_center(q_tr_traits); + typename Tr_traits::Point_weight_d tr_point_weight = + q_tr_traits.point_weight_d_object(); + + //------------------------------------------------------------------------- + //1. Compute power_center(p'q'r') in Tp => cp + //------------------------------------------------------------------------- + // CJTODO + + //------------------------------------------------------------------------- + //2. Compute power_center(inconsistent_simplex projected in Tq) + // => gives Cq and radius Rq + // Rq is also the radius of the ambient sphere S whose center is Cq and + // which goes through all the ambient points of "inconsistent_simplex" + //------------------------------------------------------------------------- + std::vector simplex_pts_in_Tq; + simplex_pts_in_Tq.reserve(inconsistent_simplex.size()); + +#ifdef CGAL_TC_PERTURB_POSITION + const Point center_pt = k_transl(m_points[q_idx], m_translations[q_idx]); +#else + const Point ¢er_pt = m_points[q_idx]; +#endif + + std::set::const_iterator it_point_idx = + inconsistent_simplex.begin(); + std::set::const_iterator it_point_idx_end = + inconsistent_simplex.end(); + // For each point p of the simplex, we reproject it onto the tangent + // space. Could be optimized since it's already been computed before. + for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) + { +#ifdef CGAL_TC_PERTURB_POSITION + const Point p = k_transl( + m_points[*it_point_idx], m_translations[*it_point_idx]); +#else + const Point &p = m_points[*it_point_idx]; +#endif +#ifdef CGAL_TC_PERTURB_WEIGHT + FT w = m_weights[*it_point_idx]; +#else + FT w = 0; +#endif + simplex_pts_in_Tq.push_back(project_point_and_compute_weight( + p, w, center_pt, m_tangent_spaces[q_idx], q_tr_traits)); + } + + Tr_point Cq = tr_power_center( + simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); + + //------------------------------------------------------------------------- + //3. Find points t1, t2... (in ambient space) which are inside S + //------------------------------------------------------------------------- + + // CJTODO: on prend le point le plus proche pour l'instant, mais il + // faudra changer a (cf 4 5 6, ci dessous) + Point global_Cq = unproject_point(Cq, center_pt, + m_tangent_spaces[q_idx], q_tr_traits); + std::size_t inside_point_idx; + INS_range ins_range = m_points_ds.query_incremental_ANN(global_Cq); + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { + std::size_t neighbor_point_idx = nn_it->first; + if (inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) + { + inside_point_idx = neighbor_point_idx; + break; + } + } + + //std::size_t inside_point_idx = kns_range.begin()->first; + + //------------------------------------------------------------------------- + //4. S'il n'y a qu'un seul points ti, passer la dernire tape + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + //5. Pour chaque ti, calculer la sphre qui passe par p, q, r, ti dont le centre est sur la droite (cq, cq) + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + //6. Conserver le point ti tel que dist(cp, ci) soit la plus petite + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + //7. Crer un k+1-simplex (inconsistent_simplex, ti) + //------------------------------------------------------------------------- + std::set new_simplex = inconsistent_simplex; + new_simplex.insert(inside_point_idx); + + it_point_idx = new_simplex.begin(); + it_point_idx_end = new_simplex.end(); + for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) + { + insert_higher_dim_simplex_into_star(*it_point_idx, new_simplex); + } + // CJTODO: call + // check_and_solve_inconsistencies_by_adding_higher_dim_simplices + // recursively? Not sure, since the star will be parsed again from + // the beginning + } + + // Test and solve inconsistencies of a simplex. + // Returns true if some inconsistencies were found. + bool check_and_solve_inconsistencies_by_adding_higher_dim_simplices( + std::size_t tr_index, const std::set &incident_simplex) + { + bool inconsistencies_found = false; + + std::set simplex = incident_simplex; + simplex.insert(tr_index); + + // Check if the simplex is in the stars of all its vertices + std::set::const_iterator it_point_idx = simplex.begin(); + // For each point p of the simplex, we parse the incidents cells of p + // and we check if "simplex" is among them + for ( ; it_point_idx != simplex.end() ; ++it_point_idx) + { + std::size_t point_idx = *it_point_idx; + // Don't check infinite simplices + if (point_idx == std::numeric_limits::max()) + continue; + + Star const& star = m_stars[point_idx]; + + // What we're looking for is "simplex" \ point_idx + Incident_simplex ic_to_find = simplex; + ic_to_find.erase(point_idx); + + // For each cell + bool found = false; + Star::const_iterator it_inc_simplex = star.begin(); + Star::const_iterator it_inc_simplex_end = star.end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + if (*it_inc_simplex == ic_to_find) + { + found = true; + break; + } + } + + if (!found) + { + solve_inconsistency_by_adding_higher_dimensional_simplices( + tr_index, *it_point_idx, simplex); + inconsistencies_found = true; + break; + } + } + + return inconsistencies_found; + } + + void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() + { + for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) + { + bool inconsistencies_found; + do + { + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + inconsistencies_found = + check_and_solve_inconsistencies_by_adding_higher_dim_simplices( + idx, *it_inc_simplex); + + // m_stars[idx] has been modified, let's start again + // CJTODO: optimize? + if (inconsistencies_found) + break; + } + } while (inconsistencies_found); + } + + // CJTODO TEMP + std::pair stats_after = + number_of_inconsistent_simplices(false); + std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_after.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_after.first << "%" + << std::endl; + } + std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_simplices, - bool color_inconsistencies = false, - std::set > const* excluded_simplices = NULL, - bool show_excluded_vertices_in_color = false) + bool color_inconsistencies = false) { // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) - int factor = (m_intrinsic_dimension == 1 ? 2 : 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; std::size_t num_inconsistent_stars = 0; @@ -1659,100 +1887,104 @@ private: //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; color << 128 << " " << 128 << " " << 128; - // For each cell + // Gather the triangles here, with a bool saying if it's consistent + typedef std::vector, bool> > + Star_using_triangles; + Star_using_triangles star_using_triangles; + + // For each cell of the star Star::const_iterator it_inc_simplex = m_stars[idx].begin(); Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - // Don't export infinite cells - if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) - continue; - std::set c = *it_inc_simplex; c.insert(idx); std::size_t num_vertices = c.size(); - if (color_inconsistencies || excluded_simplices) + bool is_simpl_consistent = true; + if (color_inconsistencies) { - std::stringstream sstr_c; - std::size_t data; - - std::set::const_iterator it_point_idx = c.begin(); - for ( ; it_point_idx != c.end() ; ++it_point_idx) - { - data = *it_point_idx; - sstr_c << data*factor << " "; - } - - bool is_simpl_consistent = is_simplex_consistent(c); + is_simpl_consistent = is_simplex_consistent(c); if (!is_simpl_consistent) is_star_inconsistent = true; + } - // See export_vertices_to_off - if (m_intrinsic_dimension == 1) - { - sstr_c << (data*factor + 1) << " "; - ++num_vertices; - } + // If only 2 vertices, add a third one (each vertex is duplicated in + // the file when m_intrinsic dim = 2) + if (num_vertices == 2) + { + std::set tmp_c; + std::set::iterator it = c.begin(); + for ( ; it != c.end() ; ++it) + tmp_c.insert(*it * 2); + tmp_c.insert(*c.rbegin() + 1); + c = tmp_c; + } - // In order to have only one time each simplex, we only keep it - // if the lowest index is the index of the center vertex - if (*c.begin() != idx && is_simpl_consistent) - continue; - - bool excluded = - (excluded_simplices - && excluded_simplices->find(c) != excluded_simplices->end()); - - if (!excluded) - { - os << num_vertices << " " << sstr_c.str() << " "; - if (color_inconsistencies && is_simpl_consistent) - os << color.str(); - else - { - os << "255 0 0"; - ++num_inconsistent_simplices; - } - ++num_simplices; - } - else if (show_excluded_vertices_in_color) - { - os << num_vertices << " " - << sstr_c.str() << " " - << "0 0 255"; - ++num_simplices; - } + if (num_vertices <= 3) + { + star_using_triangles.push_back(std::make_pair(c, is_simpl_consistent)); } else { - std::size_t min_index = std::numeric_limits::max(); - std::size_t data; - std::stringstream sstr_c; - std::set::const_iterator it_point_idx = c.begin(); - min_index = *it_point_idx; - for ( ; it_point_idx != c.end() ; ++it_point_idx) + // num_vertices >= 4: decompose the simplex in triangles + std::vector booleans(num_vertices, false); + std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); + do { - data = *it_point_idx; - sstr_c << data*factor << " "; - } - - // In order to have only one time each simplex, we only keep it - // if the lowest index is the index of the center vertex - if (min_index != idx) - continue; + std::set triangle; + std::set::iterator it = c.begin(); + for (int i = 0; it != c.end() ; ++i, ++it) + { + if (booleans[i]) + triangle.insert(*it); + } + star_using_triangles.push_back( + std::make_pair(triangle, is_simpl_consistent)); + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + } - // See export_vertices_to_off - if (m_intrinsic_dimension == 1) - { - sstr_c << (data*factor + 1) << " "; - ++num_vertices; - } + // For each cell + Star_using_triangles::const_iterator it_simplex = + star_using_triangles.begin(); + Star_using_triangles::const_iterator it_simplex_end = + star_using_triangles.end(); + for ( ; it_simplex != it_simplex_end ; ++it_simplex) + { + // Don't export infinite cells + if (*it_simplex->first.rbegin() + == std::numeric_limits::max()) + continue; + + const std::set &c = it_simplex->first; + bool is_simpl_consistent = it_simplex->second; - os << num_vertices << " " << sstr_c.str(); - ++num_simplices; + std::stringstream sstr_c; + + std::set::const_iterator it_point_idx = c.begin(); + for ( ; it_point_idx != c.end() ; ++it_point_idx) + { + sstr_c << *it_point_idx << " "; } + // In order to have only one time each simplex, we only keep it + // if the lowest index is the index of the center vertex + if (*c.begin() != idx && is_simpl_consistent) + continue; + + os << 3 << " " << sstr_c.str(); + if (color_inconsistencies) + { + if (is_simpl_consistent) + os << " " << color.str(); + else + { + os << " 255 0 0"; + ++num_inconsistent_simplices; + } + } + ++num_simplices; os << std::endl; } if (is_star_inconsistent) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 69f6f54f02e..cc9536db937 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -100,8 +100,7 @@ int main() tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - std::set > incorrect_simplices; - //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + tc.check_if_all_simplices_are_in_the_ambient_delaunay(); double export_before_time = -1.; if (INTRINSIC_DIMENSION <= 3) @@ -111,7 +110,7 @@ int main() output_filename << "output/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << "_BEFORE_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); + tc.export_to_off(off_stream, true); export_before_time = t.elapsed(); t.reset(); } @@ -134,7 +133,7 @@ int main() output_filename << "output/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); + tc.export_to_off(off_stream, true); export_after_time = t.elapsed(); t.reset(); } /*else From 0029c57ab11151dee761d9afbfbf5f5c72414320 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 16 Feb 2015 18:39:09 +0100 Subject: [PATCH 218/487] Partially parallelized fix_inconsistencies Does not work for position perturbation for now. --- .../include/CGAL/Tangential_complex.h | 44 +++++++--- .../CGAL/Tangential_complex/utilities.h | 83 +++++++++++++++++++ 2 files changed, 116 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 52592f7a0bc..d2255884bd4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -56,9 +56,11 @@ #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include +# include //# include #endif @@ -123,6 +125,17 @@ class Tangential_complex typedef std::vector Points; typedef std::vector Weights; +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH)\ + && !defined(CGAL_TC_PERTURB_POSITION) // CJTODO TEMP + // C++11 + typedef Atomic_wrapper Translation_for_perturb; + typedef std::vector > Weights_for_perturb; +#else + typedef Vector Translation_for_perturb; + typedef std::vector Weights_for_perturb; +#endif + typedef std::vector Translations_for_perturb; + typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; @@ -398,18 +411,23 @@ public: { std::size_t num_inconsistent_local_tr = 0; // CJTODO: the parallel version is not working for now -/*#ifdef CGAL_LINKED_WITH_TBB +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) \ + && !defined(CGAL_TC_PERTURB_POSITION) // CJTODO TEMP // Parallel if (boost::is_convertible::value) { + tbb::combinable num_inconsistencies; tbb::parallel_for( tbb::blocked_range(0, m_triangulations.size()), - Try_to_solve_inconsistencies_in_a_local_triangulation(*this) + Try_to_solve_inconsistencies_in_a_local_triangulation( + *this, num_inconsistencies) ); + num_inconsistent_local_tr = + num_inconsistencies.combine(std::plus()); } // Sequential else -#endif // CGAL_LINKED_WITH_TBB*/ +#endif // CGAL_LINKED_WITH_TBB { #ifdef CGAL_TC_PROFILING Wall_clock_timer t; @@ -1286,25 +1304,29 @@ private: class Try_to_solve_inconsistencies_in_a_local_triangulation { Tangential_complex & m_tc; + tbb::combinable &m_num_inconsistencies; public: // Constructor Try_to_solve_inconsistencies_in_a_local_triangulation( - Tangential_complex &tc) - : m_tc(tc) + Tangential_complex &tc, tbb::combinable &num_inconsistencies) + : m_tc(tc), m_num_inconsistencies(num_inconsistencies) {} // Constructor Try_to_solve_inconsistencies_in_a_local_triangulation( const Compute_tangent_triangulation &ctt) - : m_tc(ctt.m_tc) + : m_tc(ctt.m_tc), m_num_inconsistencies(ctt.m_num_inc) {} // operator() void operator()( const tbb::blocked_range& r ) const { for( size_t i = r.begin() ; i != r.end() ; ++i) - m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i); + { + m_num_inconsistencies.local() += + m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i); + } } }; #endif // CGAL_LINKED_WITH_TBB @@ -1348,7 +1370,7 @@ private: Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( *tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[point_idx]; + Translation_for_perturb &global_transl = m_translations[point_idx]; global_transl = k_constr_vec(m_ambiant_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) @@ -2024,13 +2046,13 @@ private: Points m_points; #ifdef CGAL_TC_PERTURB_WEIGHT - Weights m_weights; + Weights_for_perturb m_weights; #endif #ifdef CGAL_TC_PERTURB_POSITION - Vectors m_translations; + Translations_for_perturb m_translations; #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE - std::vector m_perturb_tangent_space; + std::vector > m_perturb_tangent_space; #endif Points_ds m_points_ds; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index fa55b4f332c..6e7e3e6faff 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -25,10 +25,93 @@ #include #include +#include // C++11 namespace CGAL { namespace Tangential_complex_ { + // Provides copy constructors to std::atomic so that + // it can be used in a vector + template + struct Atomic_wrapper + : public std::atomic + { + typedef std::atomic Base; + + Atomic_wrapper() {} + Atomic_wrapper(const T &t) : Base(t) {} + Atomic_wrapper(const std::atomic &a) : Base(a.load()) {} + Atomic_wrapper(const Atomic_wrapper &other) : Base(other.load()) + {} + + Atomic_wrapper &operator=(const T &other) + { + Base::store(other); + return *this; + } + Atomic_wrapper &operator=(const std::atomic &other) + { + Base::store(other.load()); + return *this; + } + Atomic_wrapper &operator=(const Atomic_wrapper &other) + { + Base::store(other.load()); + return *this; + } + }; + + /*template + struct Atomic_wrapper + { + std::atomic _a; + + Atomic_wrapper() + :_a() + {} + + Atomic_wrapper(const std::atomic &other) + :_a(other.load()) + {} + + Atomic_wrapper(const Atomic_wrapper &other) + :_a(other._a.load()) + {} + + Atomic_wrapper(const T &other) + :_a(other) + {} + + Atomic_wrapper &operator=(const std::atomic &other) + { + _a.store(other._a.load()); + return *this; + } + + Atomic_wrapper &operator=(const Atomic_wrapper &other) + { + _a.store(other._a.load()); + return *this; + } + + Atomic_wrapper &operator=(const T &other) + { + _a.store(other); + return *this; + } + + operator T() const + { + return _a.load(); + } + + operator std::atomic() const + { + return _a; + } + };*/ + + template std::vector compute_gram_schmidt_basis( From c4bf91668663fda47d2069eb788792746e9cf7bb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Feb 2015 08:37:41 +0100 Subject: [PATCH 219/487] Position perturbation is now parallel And it's almost 10x faster on 10 cores --- .../include/CGAL/Tangential_complex.h | 82 ++++++++++++++----- .../CGAL/Tangential_complex/utilities.h | 3 +- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d2255884bd4..52dff2888c4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -61,7 +61,7 @@ #ifdef CGAL_LINKED_WITH_TBB # include # include -//# include +# include #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) @@ -125,10 +125,9 @@ class Tangential_complex typedef std::vector Points; typedef std::vector Weights; -#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH)\ - && !defined(CGAL_TC_PERTURB_POSITION) // CJTODO TEMP - // C++11 - typedef Atomic_wrapper Translation_for_perturb; +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + typedef tbb::mutex Mutex_for_perturb; + typedef Vector Translation_for_perturb; typedef std::vector > Weights_for_perturb; #else typedef Vector Translation_for_perturb; @@ -218,6 +217,9 @@ public: m_ambiant_dim(k.point_dimension_d_object()(*first)), m_points(first, last), m_points_ds(m_points) +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + , m_p_perturb_mutexes(NULL) +# endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) @@ -225,7 +227,12 @@ public: {} /// Destructor - ~Tangential_complex() {} + ~Tangential_complex() + { +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + delete [] m_p_perturb_mutexes; +#endif + } std::size_t number_of_vertices() { @@ -253,6 +260,10 @@ public: #ifdef CGAL_TC_PERTURB_POSITION m_translations.resize(m_points.size(), m_k.construct_vector_d_object()(m_ambiant_dim)); +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + delete [] m_p_perturb_mutexes; + m_p_perturb_mutexes = new Mutex_for_perturb[m_points.size()]; +# endif #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE m_perturb_tangent_space.resize(m_points.size(), false); @@ -410,10 +421,13 @@ public: while (!done) { std::size_t num_inconsistent_local_tr = 0; -// CJTODO: the parallel version is not working for now -#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) \ - && !defined(CGAL_TC_PERTURB_POSITION) // CJTODO TEMP + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_fix_step; +#endif + // Parallel +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) if (boost::is_convertible::value) { tbb::combinable num_inconsistencies; @@ -429,20 +443,18 @@ public: else #endif // CGAL_LINKED_WITH_TBB { -#ifdef CGAL_TC_PROFILING - Wall_clock_timer t; -#endif for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) { num_inconsistent_local_tr += (try_to_solve_inconsistencies_in_a_local_triangulation(i) ? 1 : 0); } -#ifdef CGAL_TC_PROFILING - std::cerr << "Attempt to fix inconsistencies: " << t.elapsed() - << " seconds." << std::endl; -#endif } +#ifdef CGAL_TC_PROFILING + std::cerr << "Attempt to fix inconsistencies: " << t_fix_step.elapsed() + << " seconds." << std::endl; +#endif + #ifdef CGAL_TC_GLOBAL_REFRESH refresh_tangential_complex(); #endif @@ -864,6 +876,8 @@ private: typename Get_functor::type power_center(local_tr_traits); #ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions const Point center_pt = k_transl(m_points[i], m_translations[i]); #else const Point ¢er_pt = m_points[i]; @@ -928,6 +942,8 @@ private: if (neighbor_point_idx != i) { #ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions const Point neighbor_pt = k_transl( m_points[neighbor_point_idx], m_translations[neighbor_point_idx]); #else @@ -1349,9 +1365,19 @@ private: m_k.point_to_vector_d_object(); CGAL::Random_points_on_sphere_d tr_point_on_sphere_generator(m_ambiant_dim, 1); - + // Parallel +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + Vector transl = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), m_half_sparsity); + m_p_perturb_mutexes[point_idx].lock(); + m_translations[point_idx] = transl; + m_p_perturb_mutexes[point_idx].unlock(); + // Sequential +# else m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( *tr_point_on_sphere_generator++), m_half_sparsity); +# endif + # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL const Tr_traits &local_tr_traits = m_triangulations[point_idx].tr().geom_traits(); @@ -1370,8 +1396,7 @@ private: Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( *tr_point_on_sphere_generator++, 0); - Translation_for_perturb &global_transl = m_translations[point_idx]; - global_transl = k_constr_vec(m_ambiant_dim); + Translation_for_perturb global_transl = k_constr_vec(m_ambiant_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { @@ -1380,7 +1405,17 @@ private: k_scaled_vec(tsb[i], m_half_sparsity*coord(local_random_transl, i)) ); } -# endif + // Parallel +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + m_p_perturb_mutexes[point_idx].lock(); + m_translations[point_idx] = global_transl; + m_p_perturb_mutexes[point_idx].unlock(); + // Sequential +# else + m_translations[point_idx] = global_transl; +# endif + +# endif // CGAL_TC_PERTURB_POSITION_TANGENTIAL #endif // CGAL_TC_PERTURB_POSITION } @@ -1708,6 +1743,8 @@ private: simplex_pts_in_Tq.reserve(inconsistent_simplex.size()); #ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions const Point center_pt = k_transl(m_points[q_idx], m_translations[q_idx]); #else const Point ¢er_pt = m_points[q_idx]; @@ -1722,6 +1759,8 @@ private: for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { #ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions const Point p = k_transl( m_points[*it_point_idx], m_translations[*it_point_idx]); #else @@ -2050,6 +2089,9 @@ private: #endif #ifdef CGAL_TC_PERTURB_POSITION Translations_for_perturb m_translations; +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + Mutex_for_perturb *m_p_perturb_mutexes; +# endif #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE std::vector > m_perturb_tangent_space; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 6e7e3e6faff..bf3e70cb7c1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -25,7 +25,8 @@ #include #include -#include // C++11 +#include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) + // or tbb::atomic (works for doubles, but not officially) namespace CGAL { namespace Tangential_complex_ { From 5db662c0c2838bfc2a83ed9828c5e7e7dc6493cb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Feb 2015 10:53:58 +0100 Subject: [PATCH 220/487] Fix order of initialization --- Tangential_complex/include/CGAL/Tangential_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 52dff2888c4..334e5d1a91f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -215,11 +215,11 @@ public: m_half_sparsity(0.5*sparsity), m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), m_ambiant_dim(k.point_dimension_d_object()(*first)), - m_points(first, last), - m_points_ds(m_points) + m_points(first, last) # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) # endif + , m_points_ds(m_points) #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) From f5c1e2a7e04f7c42b01556f1009d107ce18e1078 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Feb 2015 18:06:07 +0100 Subject: [PATCH 221/487] First try with complex collapsing --- .../include/CGAL/Tangential_complex.h | 158 +++++++++++++++- .../Tangential_complex/Simplicial_complex.h | 172 ++++++++++++++++++ .../CGAL/Tangential_complex/utilities.h | 24 +++ 3 files changed, 349 insertions(+), 5 deletions(-) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 334e5d1a91f..82006ec1156 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,6 +23,9 @@ #define TANGENTIAL_COMPLEX_H #include +#include +#include +#include #include #include @@ -32,8 +35,6 @@ #include #include #include -#include -#include #include #include @@ -57,6 +58,7 @@ #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -525,6 +527,13 @@ public: std::cerr << "Time limit reached." << std::endl; #endif check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); // CJTODO: make it optional? + Simplicial_complex complex; // CJTODO: don't do it here + int max_dim = export_TC(complex); + complex.collapse(max_dim); + complex.display_stats(); + + std::ofstream off_stream("output/test.off"); // CJTODO TEMP TEST + export_to_off(complex, off_stream); return TIME_LIMIT_REACHED; } @@ -592,8 +601,43 @@ public: return std::make_pair(num_simplices, num_inconsistent_simplices); } + // Return the max dimension of the simplices + int export_TC(Simplicial_complex &complex) + { + int max_dim = -1; + + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + { + Triangulation const& tr = it_tr->tr(); + + // For each cell of the star + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + std::set c = *it_inc_simplex; + if (static_cast(c.size()) > max_dim) + max_dim = static_cast(c.size()); + // Add the missing center vertex + c.insert(idx); + complex.add_simplex(c); + } + } + return max_dim; + } + std::ostream &export_to_off( - std::ostream & os, bool color_inconsistencies = false) + const Simplicial_complex &complex, std::ostream & os) + { + return export_to_off(os, false, &complex); + } + + std::ostream &export_to_off( + std::ostream & os, bool color_inconsistencies = false, + const Simplicial_complex *p_complex = NULL) { if (m_points.empty()) return os; @@ -628,8 +672,12 @@ public: std::stringstream output; std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); - export_simplices_to_off( - output, num_simplices, color_inconsistencies); + if (p_complex) + export_simplices_to_off( + *p_complex, output, num_simplices, color_inconsistencies); + else + export_simplices_to_off( + output, num_simplices, color_inconsistencies); #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; @@ -2076,6 +2124,106 @@ private: return os; } + + std::ostream &export_simplices_to_off( + const Simplicial_complex &complex, + std::ostream & os, std::size_t &num_simplices, + bool color_inconsistencies = false) + { + typedef Simplicial_complex::Simplex Simplex; + typedef Simplicial_complex::Simplex_range Simplex_range; + + // If m_intrinsic_dimension = 1, each point is output two times + // (see export_vertices_to_off) + num_simplices = 0; + typename Simplex_range::const_iterator it_s = + complex.simplex_range().begin(); + typename Simplex_range::const_iterator it_s_end = + complex.simplex_range().end(); + // For each triangulation + for ( ; it_s != it_s_end ; ++it_s) + { + Simplex c = *it_s; + + // Gather the triangles here, with a bool saying if it's consistent + typedef std::vector Triangles; + Triangles triangles; + + std::size_t num_vertices = c.size(); + // Do not export smaller dimension simplices + if (num_vertices < m_intrinsic_dimension + 1) + continue; + + // If only 2 vertices, add a third one (each vertex is duplicated in + // the file when m_intrinsic dim = 2) + if (num_vertices == 2) + { + std::set tmp_c; + std::set::iterator it = c.begin(); + for ( ; it != c.end() ; ++it) + tmp_c.insert(*it * 2); + tmp_c.insert(*c.rbegin() + 1); + c = tmp_c; + } + + if (num_vertices <= 3) + { + triangles.push_back(c); + } + else + { + // num_vertices >= 4: decompose the simplex in triangles + std::vector booleans(num_vertices, false); + std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); + do + { + std::set triangle; + std::set::iterator it = c.begin(); + for (int i = 0; it != c.end() ; ++i, ++it) + { + if (booleans[i]) + triangle.insert(*it); + } + triangles.push_back(triangle); + } + while (std::next_permutation(booleans.begin(), booleans.end())); + } + + // For each cell + Triangles::const_iterator it_tri = triangles.begin(); + Triangles::const_iterator it_tri_end = triangles.end(); + for ( ; it_tri != it_tri_end ; ++it_tri) + { + // Don't export infinite cells + if (*it_tri->rbegin() == std::numeric_limits::max()) + continue; + + os << 3 << " "; + std::set::const_iterator it_point_idx = it_tri->begin(); + for ( ; it_point_idx != it_tri->end() ; ++it_point_idx) + { + os << *it_point_idx << " "; + } + + ++num_simplices; + os << std::endl; + } + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "==========================================================" + << std::endl + << "Export to OFF:\n" + << " * Number of vertices: " << m_points.size() << std::endl + << " * Total number of simplices: " << num_simplices << std::endl + << "==========================================================" + << std::endl; +#endif + + return os; + } + private: const Kernel m_k; const int m_intrinsic_dimension; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h new file mode 100644 index 00000000000..1fbda4dd9a5 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -0,0 +1,172 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin + + +#ifndef SIMPLICIAL_COMPLEX_H +#define SIMPLICIAL_COMPLEX_H + +#include +#include + +#include + +namespace CGAL { + +using namespace Tangential_complex_; + +class Simplicial_complex +{ +public: + typedef std::set Simplex; + typedef std::set Simplex_range; + + void add_simplex(const std::set &s) + { + m_complex.insert(s); + } + + const Simplex_range &simplex_range() const + { + return m_complex; + } + + void collapse(int max_simplex_dim) + { + // We note k = max_simplex_dim - 1 + int k = max_simplex_dim - 1; + + typedef Complex::iterator Simplex_iterator; + typedef std::vector Simplex_iterator_list; + typedef std::map Cofaces_map; + + // Create a map associating each non-maximal k-faces to the list of its + // maximal cofaces + Cofaces_map cofaces_map; + for (Complex::const_iterator it_simplex = m_complex.begin(), + it_simplex_end = m_complex.end() ; + it_simplex != it_simplex_end ; + ++it_simplex) + { + if (it_simplex->size() > k + 1) + { + std::vector k_faces; + // Get the k-faces composing the simplex + combinations(*it_simplex, k + 1, std::back_inserter(k_faces)); + for (const auto &comb : k_faces) // CJTODO C++1 + cofaces_map[comb].push_back(it_simplex); + } + } + + // For each non-maximal k-face F, if F has only one maximal coface Cf: + // - Look for the other k-faces F2 of Cf in the map and: + // * if the list contains only Cf, clear the list (we don't remove the + // list since it was create troubles with the iterators) and add f2 + // to the complex + // * otherwise, remove Cf from the associated list + // - Remove Cf from the complex + for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(), + it_map_end = cofaces_map.end() ; + it_map_elt != it_map_end ; + ++it_map_elt) + { + if (it_map_elt->second.size() == 1) + { + std::vector k_faces; + const Simplex_iterator_list::value_type &it_Cf = + *it_map_elt->second.begin(); + CGAL_assertion(it_Cf->size() == max_simplex_dim + 1); + // Get the k-faces composing the simplex + combinations(*it_Cf, k + 1, std::back_inserter(k_faces)); + for (const auto &f2 : k_faces) // CJTODO C++1 + { + if (f2 != it_map_elt->first) + { + Cofaces_map::iterator it_comb_in_map = cofaces_map.find(f2); + if (it_comb_in_map->second.size() == 1) + { + it_comb_in_map->second.clear(); + m_complex.insert(f2); + } + else // it_comb_in_map->second.size() > 1 + { + Simplex_iterator_list::iterator it = std::find( + it_comb_in_map->second.begin(), + it_comb_in_map->second.end(), + it_Cf); + CGAL_assertion(it != it_comb_in_map->second.end()); + it_comb_in_map->second.erase(it); + } + } + } + m_complex.erase(it_Cf); + } + } + + // Collapse the lower dimension simplices + if (k > 1) + collapse(max_simplex_dim - 1); + } + + void display_stats() const + { + std::cerr << "==========================================================\n"; + std::cerr << "Complex stats:\n"; + + if (m_complex.empty()) + { + std::cerr << "No simplices.\n"; + } + else + { + // Number of simplex for each dimension + std::map simplex_stats; + + typedef std::set Simplex; + typedef std::set Complex; + + for (Complex::const_iterator it_simplex = m_complex.begin(), + it_simplex_end = m_complex.end() ; + it_simplex != it_simplex_end ; + ++it_simplex) + { + ++simplex_stats[static_cast(it_simplex->size()) - 1]; + } + + for (std::map::const_iterator it_map = simplex_stats.begin() ; + it_map != simplex_stats.end() ; ++it_map) + { + std::cerr << " * " << it_map->first << "-simplices: " + << it_map->second << std::endl; + } + } + + std::cerr << "==========================================================\n"; + } + +private: + typedef Simplex_range Complex; + + Complex m_complex; + +}; // /class Simplicial_complex + +} // end namespace CGAL + +#endif // SIMPLICIAL_COMPLEX_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index bf3e70cb7c1..639ce0a8f0d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -24,6 +24,7 @@ #include #include +#include #include #include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) @@ -151,6 +152,29 @@ namespace Tangential_complex_ { return output_basis; } + + // Compute all the k-combinations of elements + // Output_iterator::value_type must be std::set > + template + void combinations(const Elements_container elements, int k, + Output_iterator combinations) + { + std::size_t n = elements.size(); + std::vector booleans(n, false); + std::fill(booleans.begin() + n - k, booleans.end(), true); + do + { + std::set combination; + Elements_container::const_iterator it_elt = elements.begin(); + for (std::size_t i = 0 ; i < n ; ++i, ++it_elt) + { + if (booleans[i]) + combination.insert(*it_elt); + } + *combinations++ = combination; + + } while (std::next_permutation(booleans.begin(), booleans.end())); + } } // namespace Tangential_complex_ } //namespace CGAL From 1e11e67859109d695995028a0d195ee9f2b24586 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Feb 2015 13:49:46 +0100 Subject: [PATCH 222/487] Moved code around + updated check_if_all_simplices_are_in_the_ambient_delaunay --- .../Tangential_complex/benchmark_tc.cpp | 12 +- .../include/CGAL/Tangential_complex.h | 218 ++++++++++-------- .../Tangential_complex/Simplicial_complex.h | 56 ++++- .../CGAL/Tangential_complex/utilities.h | 1 + 4 files changed, 188 insertions(+), 99 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ed55aa637db..46e4264356b 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -205,14 +205,24 @@ void make_tc(std::vector &points, int intrinsic_dim, best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, time_limit_for_fix); double fix_time = t.elapsed(); t.reset(); - + CGAL_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", initial_num_inconsistent_local_tr); CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", best_num_inconsistent_local_tr); CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", final_num_inconsistent_local_tr); + + tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + TC::Simplicial_complex complex; + int max_dim = tc.export_TC(complex); + tc.check_if_all_simplices_are_in_the_ambient_delaunay(&complex); + complex.collapse(max_dim); + complex.display_stats(); + std::ofstream off_stream("output/test.off"); // CJTODO TEMP TEST + tc.export_to_off(complex, off_stream); + double export_after_time = -1.; if (intrinsic_dim <= 3) { diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 82006ec1156..2f3ac0fb9ec 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -203,6 +203,8 @@ class Tangential_complex public: + typedef Tangential_complex_::Simplicial_complex Simplicial_complex; + /// Constructor for a range of points template Tangential_complex(InputIterator first, InputIterator last, @@ -526,15 +528,6 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Time limit reached." << std::endl; #endif - check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); // CJTODO: make it optional? - Simplicial_complex complex; // CJTODO: don't do it here - int max_dim = export_TC(complex); - complex.collapse(max_dim); - complex.display_stats(); - - std::ofstream off_stream("output/test.off"); // CJTODO TEMP TEST - export_to_off(complex, off_stream); - return TIME_LIMIT_REACHED; } } @@ -628,7 +621,43 @@ public: } return max_dim; } - + + void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() + { + for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) + { + bool inconsistencies_found; + do + { + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + inconsistencies_found = + check_and_solve_inconsistencies_by_adding_higher_dim_simplices( + idx, *it_inc_simplex); + + // m_stars[idx] has been modified, let's start again + // CJTODO: optimize? + if (inconsistencies_found) + break; + } + } while (inconsistencies_found); + } + + // CJTODO TEMP + std::pair stats_after = + number_of_inconsistent_simplices(false); + std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_after.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_after.first << "%" + << std::endl; + } + std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os) { @@ -693,8 +722,13 @@ public: } bool check_if_all_simplices_are_in_the_ambient_delaunay( + const Simplicial_complex *p_complex = NULL, + bool check_for_any_dimension_simplices = true, std::set > * incorrect_simplices = NULL) { + typedef Simplicial_complex::Simplex Simplex; + typedef Simplicial_complex::Simplex_range Simplex_range; + if (m_points.empty()) return true; @@ -706,7 +740,6 @@ public: > > DT; typedef typename DT::Vertex_handle DT_VH; typedef typename DT::Finite_full_cell_const_iterator FFC_it; - typedef std::set Indexed_simplex; //------------------------------------------------------------------------- // Build the ambient Delaunay triangulation @@ -721,69 +754,89 @@ public: vh->data() = i; } - std::set amb_dt_simplices; + std::set amb_dt_simplices; for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; cit != ambient_dt.finite_full_cells_end() ; ++cit ) { - CGAL::Combination_enumerator combi( - m_intrinsic_dimension + 1, 0, ambient_dim + 1); + int lowest_dim = + (check_for_any_dimension_simplices ? 1 : m_intrinsic_dimension); + int highest_dim = + (check_for_any_dimension_simplices ? ambient_dim : m_intrinsic_dimension); - for ( ; !combi.finished() ; ++combi) + for (int dim = lowest_dim ; dim <= highest_dim ; ++dim) { - Indexed_simplex simplex; - for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) - simplex.insert(cit.base()->vertex(combi[i])->data()); + CGAL::Combination_enumerator combi( + dim + 1, 0, ambient_dim + 1); - amb_dt_simplices.insert(simplex); - } - } - - //------------------------------------------------------------------------- - // Parse the TC and save its simplices into "stars_simplices" - //------------------------------------------------------------------------- - - std::set stars_simplices; - - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); - // For each triangulation - for ( ; it_tr != it_tr_end ; ++it_tr) - { - Triangulation const& tr = it_tr->tr(); - Tr_vertex_handle center_vh = it_tr->center_vertex(); - - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - typename std::vector::const_iterator it_c = - incident_cells.begin(); - typename std::vector::const_iterator it_c_end = - incident_cells.end(); - // For each cell - for ( ; it_c != it_c_end ; ++it_c) - { - if (tr.is_infinite(*it_c)) + for ( ; !combi.finished() ; ++combi) { - std::cerr << "Warning: infinite cell in star" << std::endl; - continue; - } - Indexed_simplex simplex; - for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) - simplex.insert((*it_c)->vertex(i)->data()); + Simplex simplex; + for (int i = 0 ; i < dim + 1 ; ++i) + simplex.insert(cit.base()->vertex(combi[i])->data()); - stars_simplices.insert(simplex); + amb_dt_simplices.insert(simplex); + } } } //------------------------------------------------------------------------- - // Check if simplices of "stars_simplices" are all in "amb_dt_simplices" + // If p_complex is NULL, parse the TC and + // save its simplices into "stars_simplices" //------------------------------------------------------------------------- - std::set diff; + Simplex_range const *p_simplices; + + if (!p_complex) + { + Simplex_range stars_simplices; + + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + typename std::vector::const_iterator it_c = + incident_cells.begin(); + typename std::vector::const_iterator it_c_end = + incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + if (tr.is_infinite(*it_c)) + { + std::cerr << "Warning: infinite cell in star" << std::endl; + continue; + } + Simplex simplex; + for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) + simplex.insert((*it_c)->vertex(i)->data()); + + stars_simplices.insert(simplex); + } + } + + p_simplices = &stars_simplices; + } + else + { + p_simplices = &p_complex->simplex_range(); + } + + //------------------------------------------------------------------------- + // Check if simplices of "*p_complex" are all in "amb_dt_simplices" + //------------------------------------------------------------------------- + + std::set diff; if (!incorrect_simplices) incorrect_simplices = &diff; - set_difference(stars_simplices.begin(), stars_simplices.end(), + set_difference(p_simplices->begin(), p_simplices->end(), amb_dt_simplices.begin(), amb_dt_simplices.end(), std::inserter(*incorrect_simplices, incorrect_simplices->begin()) ); @@ -795,14 +848,27 @@ public: << std::endl << " Number of simplices in ambient DT: " << amb_dt_simplices.size() << std::endl - << " Number of unique simplices in TC stars: " << stars_simplices.size() + << " Number of unique simplices in TC stars: " << p_simplices->size() << std::endl << " Number of wrong simplices: " << incorrect_simplices->size() << std::endl; return false; } else + { +#ifdef CGAL_TC_VERBOSE + std::cerr + << "SUCCESS check_if_all_simplices_are_in_the_ambient_delaunay:" + << std::endl + << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << std::endl + << " Number of unique simplices in TC stars: " << p_simplices->size() + << std::endl + << " Number of wrong simplices: " << incorrect_simplices->size() + << std::endl; +#endif return true; + } } private: @@ -1933,42 +1999,6 @@ private: return inconsistencies_found; } - void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() - { - for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) - { - bool inconsistencies_found; - do - { - Star::const_iterator it_inc_simplex = m_stars[idx].begin(); - Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); - for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) - { - inconsistencies_found = - check_and_solve_inconsistencies_by_adding_higher_dim_simplices( - idx, *it_inc_simplex); - - // m_stars[idx] has been modified, let's start again - // CJTODO: optimize? - if (inconsistencies_found) - break; - } - } while (inconsistencies_found); - } - - // CJTODO TEMP - std::pair stats_after = - number_of_inconsistent_simplices(false); - std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%" - << std::endl; - } - std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_simplices, bool color_inconsistencies = false) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 1fbda4dd9a5..445864ceb67 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -28,8 +28,7 @@ #include namespace CGAL { - -using namespace Tangential_complex_; +namespace Tangential_complex_ { class Simplicial_complex { @@ -123,7 +122,7 @@ public: if (k > 1) collapse(max_simplex_dim - 1); } - + void display_stats() const { std::cerr << "==========================================================\n"; @@ -160,6 +159,54 @@ public: std::cerr << "==========================================================\n"; } + // CJTODO: this is only based on the fact that each edge should have two + // cofaces + bool is_manifold(bool exit_at_the_first_problem = true) + { + typedef std::set Edge; + typedef std::map Cofaces_map; + + // Counts the number of cofaces of each edge + + // Create a map associating each non-maximal k-faces to the list of its + // maximal cofaces + Cofaces_map cofaces_map; + for (Complex::const_iterator it_simplex = m_complex.begin(), + it_simplex_end = m_complex.end() ; + it_simplex != it_simplex_end ; + ++it_simplex) + { + if (it_simplex->size() > 2) + { + std::vector edges; + // Get the k-faces composing the simplex + combinations(*it_simplex, 2, std::back_inserter(edges)); + for (const auto &edge : edges) // CJTODO C++1 + { + ++cofaces_map[edge]; + } + } + } + + bool manifold = true; + for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(), + it_map_end = cofaces_map.end() ; + it_map_elt != it_map_end ; + ++it_map_elt) + { + if (it_map_elt->second != 2) + { + std::cerr << "Found an edge with " << it_map_elt->second << " cofaces\n"; + if (exit_at_the_first_problem) + return false; + else + manifold = false; + } + } + + return manifold; + } + private: typedef Simplex_range Complex; @@ -167,6 +214,7 @@ private: }; // /class Simplicial_complex -} // end namespace CGAL +} // namespace Tangential_complex_ +} //namespace CGAL #endif // SIMPLICIAL_COMPLEX_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 639ce0a8f0d..a15c38f13f8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -153,6 +153,7 @@ namespace Tangential_complex_ { return output_basis; } + // CJTODO: use CGAL::Combination_enumerator (cf. Tangential_complex.h) // Compute all the k-combinations of elements // Output_iterator::value_type must be std::set > template From 9dbdaf42c440ef88e75667170ebc40a50813343f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Feb 2015 22:56:37 +0100 Subject: [PATCH 223/487] Better export + debug code --- .../include/CGAL/Tangential_complex.h | 130 ++++++++++++++---- 1 file changed, 102 insertions(+), 28 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2f3ac0fb9ec..b499f8b1160 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -220,7 +220,8 @@ public: m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), m_ambiant_dim(k.point_dimension_d_object()(*first)), m_points(first, last) -# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ + && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) # endif , m_points_ds(m_points) @@ -233,7 +234,8 @@ public: /// Destructor ~Tangential_complex() { -#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ + && defined(CGAL_TC_GLOBAL_REFRESH) delete [] m_p_perturb_mutexes; #endif } @@ -595,7 +597,8 @@ public: } // Return the max dimension of the simplices - int export_TC(Simplicial_complex &complex) + int export_TC(Simplicial_complex &complex, + bool export_infinite_simplices = false) { int max_dim = -1; @@ -611,6 +614,11 @@ public: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { + // Don't export infinite cells + if (!export_infinite_simplices && *it_inc_simplex->rbegin() + == std::numeric_limits::max()) + continue; + std::set c = *it_inc_simplex; if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); @@ -657,15 +665,17 @@ public: << 100. * stats_after.second / stats_after.first << "%" << std::endl; } - + std::ostream &export_to_off( - const Simplicial_complex &complex, std::ostream & os) + const Simplicial_complex &complex, std::ostream & os, + std::set > const *p_additional_simpl_to_color = NULL) { - return export_to_off(os, false, &complex); + return export_to_off(os, false, p_additional_simpl_to_color, &complex); } - + std::ostream &export_to_off( - std::ostream & os, bool color_inconsistencies = false, + std::ostream & os, bool color_inconsistencies = false, + std::set > const *p_additional_simpl_to_color = NULL, const Simplicial_complex *p_complex = NULL) { if (m_points.empty()) @@ -702,11 +712,16 @@ public: std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); if (p_complex) + { export_simplices_to_off( - *p_complex, output, num_simplices, color_inconsistencies); + *p_complex, output, num_simplices, p_additional_simpl_to_color); + } else + { export_simplices_to_off( - output, num_simplices, color_inconsistencies); + output, num_simplices, color_inconsistencies, + p_additional_simpl_to_color); + } #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; @@ -1892,6 +1907,8 @@ private: Tr_point Cq = tr_power_center( simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); + //std::cerr << "Cq weight: " << tr_point_weight(Cq) << std::endl; // CJTODO TEMP + //------------------------------------------------------------------------- //3. Find points t1, t2... (in ambient space) which are inside S //------------------------------------------------------------------------- @@ -1911,6 +1928,36 @@ private: inconsistent_simplex.end()) { inside_point_idx = neighbor_point_idx; + + { // CJTODO TEMP DEBUG + ++nn_it; + int count_insiders = 1; + for (int count = 0 ; count < inconsistent_simplex.size() ; ++count, ++nn_it) + { + std::size_t neighbor_point_idx = nn_it->first; + if (inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) + { + //std::cerr << "insider dist: " << nn_it->second << std::endl; // CJTODO TEMP + ++count_insiders; + } + else + { + //std::cerr << "Simplex point dist: " << nn_it->second << std::endl; // CJTODO TEMP + ++count; + } + } + + if (count_insiders > 1) + { + std::cerr << "Warning: " << count_insiders << " insiders in " + << inconsistent_simplex.size() - 1 << " simplex\n"; + } + //else + // std::cerr << "Ok: only one vertex inside the sphere\n"; + + } // END CJTODO + break; } } @@ -1954,6 +2001,11 @@ private: { bool inconsistencies_found = false; + // Don't check infinite simplices + if (*incident_simplex.rbegin() + == std::numeric_limits::max()) + return false; + std::set simplex = incident_simplex; simplex.insert(tr_index); @@ -1964,9 +2016,6 @@ private: for ( ; it_point_idx != simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; - // Don't check infinite simplices - if (point_idx == std::numeric_limits::max()) - continue; Star const& star = m_stars[point_idx]; @@ -2001,7 +2050,8 @@ private: std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_simplices, - bool color_inconsistencies = false) + bool color_inconsistencies = false, + std::set > const *p_additional_simpl_to_color = NULL) { // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) @@ -2040,14 +2090,22 @@ private: c.insert(idx); std::size_t num_vertices = c.size(); - bool is_simpl_consistent = true; + bool color_simplex = false; if (color_inconsistencies) { - is_simpl_consistent = is_simplex_consistent(c); - if (!is_simpl_consistent) + color_simplex = !is_simplex_consistent(c); + if (color_simplex) is_star_inconsistent = true; } + if (p_additional_simpl_to_color && !color_simplex) + { + color_simplex = (std::find( + p_additional_simpl_to_color->begin(), + p_additional_simpl_to_color->end(), + c) != p_additional_simpl_to_color->end()); + } + // If only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) if (num_vertices == 2) @@ -2062,7 +2120,7 @@ private: if (num_vertices <= 3) { - star_using_triangles.push_back(std::make_pair(c, is_simpl_consistent)); + star_using_triangles.push_back(std::make_pair(c, color_simplex)); } else { @@ -2079,7 +2137,7 @@ private: triangle.insert(*it); } star_using_triangles.push_back( - std::make_pair(triangle, is_simpl_consistent)); + std::make_pair(triangle, color_simplex)); } while (std::next_permutation(booleans.begin(), booleans.end())); } } @@ -2097,7 +2155,7 @@ private: continue; const std::set &c = it_simplex->first; - bool is_simpl_consistent = it_simplex->second; + bool color_simplex = it_simplex->second; std::stringstream sstr_c; @@ -2109,19 +2167,19 @@ private: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != idx && is_simpl_consistent) + if (*c.begin() != idx && !color_simplex) continue; os << 3 << " " << sstr_c.str(); - if (color_inconsistencies) + if (color_inconsistencies || p_additional_simpl_to_color) { - if (is_simpl_consistent) - os << " " << color.str(); - else + if (color_simplex) { os << " 255 0 0"; ++num_inconsistent_simplices; } + else + os << " " << color.str(); } ++num_simplices; os << std::endl; @@ -2154,11 +2212,10 @@ private: return os; } - std::ostream &export_simplices_to_off( const Simplicial_complex &complex, std::ostream & os, std::size_t &num_simplices, - bool color_inconsistencies = false) + std::set > const *p_additional_simpl_to_color = NULL) { typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; @@ -2175,7 +2232,16 @@ private: { Simplex c = *it_s; - // Gather the triangles here, with a bool saying if it's consistent + bool color_simplex = false; + if (p_additional_simpl_to_color) + { + color_simplex = (std::find( + p_additional_simpl_to_color->begin(), + p_additional_simpl_to_color->end(), + c) != p_additional_simpl_to_color->end()); + } + + // Gather the triangles here typedef std::vector Triangles; Triangles triangles; @@ -2235,6 +2301,14 @@ private: os << *it_point_idx << " "; } + if (p_additional_simpl_to_color) + { + if (color_simplex) + os << " 255 0 0"; + else + os << " 128 128 128"; + } + ++num_simplices; os << std::endl; } From 70c4d330c5cd07acd1ecbb3df2fc1d19e75bbfbf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Feb 2015 22:57:27 +0100 Subject: [PATCH 224/487] More exports in the benchmark --- .../Tangential_complex/benchmark_tc.cpp | 61 ++++++++++++++----- .../include/CGAL/Tangential_complex/config.h | 4 +- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 46e4264356b..b8f795ceea5 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -213,17 +213,7 @@ void make_tc(std::vector &points, int intrinsic_dim, CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", final_num_inconsistent_local_tr); - tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); - TC::Simplicial_complex complex; - int max_dim = tc.export_TC(complex); - tc.check_if_all_simplices_are_in_the_ambient_delaunay(&complex); - complex.collapse(max_dim); - complex.display_stats(); - - std::ofstream off_stream("output/test.off"); // CJTODO TEMP TEST - tc.export_to_off(complex, off_stream); - - double export_after_time = -1.; + double export_after_fix_time = -1.; if (intrinsic_dim <= 3) { t.reset(); @@ -232,10 +222,48 @@ void make_tc(std::vector &points, int intrinsic_dim, << "_in_R" << ambient_dim << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true); - export_after_time = t.elapsed(); t.reset(); + export_after_fix_time = t.elapsed(); t.reset(); } - /*else - tc.number_of_inconsistent_simplices();*/ + + // Try to solve the remaining inconstencies + tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + TC::Simplicial_complex complex; + int max_dim = tc.export_TC(complex, false); + std::set > not_delaunay_simplices; + if (ambient_dim <= 4) + { + tc.check_if_all_simplices_are_in_the_ambient_delaunay( + &complex, true, ¬_delaunay_simplices); + } + + double export_after_fix2_time = -1.; + if (intrinsic_dim <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim + << "_in_R" << ambient_dim << "_AFTER_FIX2.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(complex, off_stream, ¬_delaunay_simplices); + export_after_fix2_time = t.elapsed(); t.reset(); + } + + // Collapse + complex.collapse(max_dim); + + double export_after_collapse_time = -1.; + if (intrinsic_dim <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim + << "_in_R" << ambient_dim << "_AFTER_COLLAPSE.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(complex, off_stream); + export_after_collapse_time = t.elapsed(); t.reset(); + } + + complex.display_stats(); std::cerr << std::endl << "================================================" << std::endl @@ -249,7 +277,10 @@ void make_tc(std::vector &points, int intrinsic_dim, << " * Fix inconsistencies: " << fix_time << " (" << num_fix_steps << " steps) ==> " << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl - << " * Export to OFF (after fix): " << export_after_time << std::endl + << " * Export to OFF (after fix): " << export_after_fix_time << std::endl + << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl + << " * Export to OFF (after collapse): " + << export_after_collapse_time << std::endl << "================================================" << std::endl << std::endl; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index f9339340dbe..47bf0147c91 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -58,10 +58,10 @@ // for local tri where there are some inconsistencies // But be careful: refreshing the TC may invalidate cells, so the // incident cells have to be recomputed again -#define CGAL_TC_PERTURB_POSITION +//#define CGAL_TC_PERTURB_POSITION # define CGAL_TC_PERTURB_POSITION_TANGENTIAL // default //# define CGAL_TC_PERTURB_POSITION_GLOBAL -//#define CGAL_TC_PERTURB_WEIGHT +#define CGAL_TC_PERTURB_WEIGHT //#define CGAL_TC_PERTURB_TANGENT_SPACE //========================= Parameters ======================================== From bdf8a6286b47e5866c5c0ee60ee4cf13c112b44d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 23 Feb 2015 17:43:30 +0100 Subject: [PATCH 225/487] Add TODOs and temporary comments --- Tangential_complex/include/CGAL/Tangential_complex.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b499f8b1160..59ea4b8baed 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -632,6 +632,7 @@ public: void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() { + // CJTODO: parallel_for for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) { bool inconsistencies_found; @@ -1915,6 +1916,10 @@ private: // CJTODO: on prend le point le plus proche pour l'instant, mais il // faudra changer a (cf 4 5 6, ci dessous) + // Et aussi, il faudra utiliser Power_distance dans le cas o on perturbe + // avec des poids (on est dans l'espace ambiant, donc ce sont les seuls + // poids possibles). Il faut aussi ajouter une marge lors de la recherche + // ANN puis restester la distance avec le vrai point perturbe. Point global_Cq = unproject_point(Cq, center_pt, m_tangent_spaces[q_idx], q_tr_traits); std::size_t inside_point_idx; From f4de16d0932a9ace0297e6433a1343528cc8dac6 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 24 Feb 2015 14:00:28 +0100 Subject: [PATCH 226/487] Link Power_center_d. --- NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h | 2 ++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index cd8269f07da..52114ff6442 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -66,6 +66,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Point_dimension_d; typedef typename Get_functor::type Side_of_oriented_sphere_d; typedef typename Get_functor::type Power_test_d; + typedef typename Get_functor::type Power_center_d; typedef typename Get_functor::type Contained_in_affine_hull_d; typedef typename Get_functor::type Construct_flat_orientation_d; typedef typename Get_functor::type In_flat_orientation_d; @@ -175,6 +176,7 @@ template struct Kernel_d_interface : public Base_ { Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); } Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } Power_test_d power_test_d_object()const{ return Power_test_d(*this); } + Power_center_d power_center_d_object()const{ return Power_center_d(*this); } Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); } Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); } diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 96ca0b4c39e..99c369a5f55 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -123,7 +123,7 @@ void test2(){ typedef typename K1::Difference_of_vectors_d DV; typedef typename K1::Difference_of_points_d DP; typedef typename K1::Translated_point_d TP; - typedef typename CGAL::Get_functor::type PC; + typedef typename K1::Power_center_d PC; typedef typename CGAL::Get_functor::type PoD; typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; @@ -187,7 +187,7 @@ void test2(){ DV dv Kinit(difference_of_vectors_d_object); DP dp Kinit(difference_of_points_d_object); TP tp Kinit(translated_point_d_object); - PC pc (k); + PC pc Kinit(power_center_d_object); CWP cwp Kinit(construct_weighted_point_d_object); PDW pdw Kinit(point_drop_weight_d_object); PW pw Kinit(point_weight_d_object); From ed6ac903843d7732e43caae7d026726de0a57b3a Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 24 Feb 2015 17:32:47 +0100 Subject: [PATCH 227/487] Link Power_distance_d. --- NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h | 2 ++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index 52114ff6442..4652e2dc17b 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -67,6 +67,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Side_of_oriented_sphere_d; typedef typename Get_functor::type Power_test_d; typedef typename Get_functor::type Power_center_d; + typedef typename Get_functor::type Power_distance_d; typedef typename Get_functor::type Contained_in_affine_hull_d; typedef typename Get_functor::type Construct_flat_orientation_d; typedef typename Get_functor::type In_flat_orientation_d; @@ -177,6 +178,7 @@ template struct Kernel_d_interface : public Base_ { Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } Power_test_d power_test_d_object()const{ return Power_test_d(*this); } Power_center_d power_center_d_object()const{ return Power_center_d(*this); } + Power_distance_d power_distance_d_object()const{ return Power_distance_d(*this); } Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); } Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); } diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 99c369a5f55..1b9dbcd45e8 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -124,7 +124,7 @@ void test2(){ typedef typename K1::Difference_of_points_d DP; typedef typename K1::Translated_point_d TP; typedef typename K1::Power_center_d PC; - typedef typename CGAL::Get_functor::type PoD; + typedef typename K1::Power_distance_d PoD; typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; typedef typename K1::Point_drop_weight_d PDW; @@ -191,7 +191,7 @@ void test2(){ CWP cwp Kinit(construct_weighted_point_d_object); PDW pdw Kinit(point_drop_weight_d_object); PW pw Kinit(point_weight_d_object); - PoD pod (k); + PoD pod Kinit(power_distance_d_object); CGAL_USE(bc); CGAL_USE(pol); From a08463fd4d79049b00f1852d32f240d5e4d6014c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 14:32:19 +0100 Subject: [PATCH 228/487] check_if_all_simplices_are_in_the_ambient_delaunay takes weights into account --- .../include/CGAL/Tangential_complex.h | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 59ea4b8baed..ecece6b9921 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -749,24 +749,26 @@ public: return true; const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); - typedef Delaunay_triangulation - > > DT; - typedef typename DT::Vertex_handle DT_VH; - typedef typename DT::Finite_full_cell_const_iterator FFC_it; + typedef Regular_triangulation_euclidean_traits RT_Traits; + typedef Regular_triangulation< + RT_Traits, + Triangulation_data_structure< + typename RT_Traits::Dimension, + Triangulation_vertex + > > RT; + typedef typename RT::Vertex_handle RT_VH; + typedef typename RT::Finite_full_cell_const_iterator FFC_it; //------------------------------------------------------------------------- // Build the ambient Delaunay triangulation // Then save its simplices into "amb_dt_simplices" //------------------------------------------------------------------------- - DT ambient_dt(ambient_dim); + RT ambient_dt(ambient_dim); for (std::size_t i=0; idata() = i; } @@ -862,7 +864,7 @@ public: std::cerr << "ERROR check_if_all_simplices_are_in_the_ambient_delaunay:" << std::endl - << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << " Number of simplices in ambient RT: " << amb_dt_simplices.size() << std::endl << " Number of unique simplices in TC stars: " << p_simplices->size() << std::endl @@ -876,7 +878,7 @@ public: std::cerr << "SUCCESS check_if_all_simplices_are_in_the_ambient_delaunay:" << std::endl - << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << " Number of simplices in ambient RT: " << amb_dt_simplices.size() << std::endl << " Number of unique simplices in TC stars: " << p_simplices->size() << std::endl From 907483a0d09f2e50bea19108345e6b79278340e4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 14:35:14 +0100 Subject: [PATCH 229/487] Remove unused classes --- .../include/CGAL/Tangential_complex.h | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ecece6b9921..2071a278936 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -909,42 +909,6 @@ private: Kernel const& m_k; }; - struct Tr_vertex_to_global_point - { - typedef Tr_vertex_handle argument_type; - typedef Point result_type; - - Tr_vertex_to_global_point(Points const& points) - : m_points(points) {} - - result_type operator()(argument_type const& vh) const - { - return m_points[vh->data()]; - } - - private: - Points const& m_points; - }; - - struct Tr_vertex_to_bare_point - { - typedef Tr_vertex_handle argument_type; - typedef Tr_bare_point result_type; - - Tr_vertex_to_bare_point(Tr_traits const& traits) - : m_traits(traits) {} - - result_type operator()(argument_type const& vh) const - { - typename Tr_traits::Point_drop_weight_d pdw = - m_traits.point_drop_weight_d_object(); - return pdw(vh->point()); - } - - private: - Tr_traits const& m_traits; - }; - #ifdef CGAL_LINKED_WITH_TBB // Functor for compute_tangential_complex function class Compute_tangent_triangulation From 91a52fe65badb1a6a925dfb2dfbe743d4a212a52 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 16:02:15 +0100 Subject: [PATCH 230/487] Improve solve_inconsistency_by_adding_higher_dimensional_simplices Now, it handles the case where more than one vertices are in the Tq-centered sphere. Also, fixes a bug with the star-sphere radius. --- .../include/CGAL/Tangential_complex.h | 493 ++++++++++++------ 1 file changed, 328 insertions(+), 165 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2071a278936..53d557d4d73 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -112,6 +112,7 @@ class Tangential_complex { typedef typename Kernel::FT FT; typedef typename Kernel::Point_d Point; + typedef typename Kernel::Weighted_point_d Weighted_point; typedef typename Kernel::Vector_d Vector; typedef Tr Triangulation; @@ -386,14 +387,17 @@ public: #endif } - // time_limit in seconds + // time_limit in seconds: 0 = no fix to do, < 0 = no time limit Fix_inconsistencies_status fix_inconsistencies( unsigned int &num_steps, std::size_t &initial_num_inconsistent_local_tr, std::size_t &best_num_inconsistent_local_tr, std::size_t &final_num_inconsistent_local_tr, - double time_limit = 0.) + double time_limit = -1.) { + if (time_limit == 0.) + return TIME_LIMIT_REACHED; + Wall_clock_timer t; typename Kernel::Point_drop_weight_d drop_w = @@ -525,7 +529,7 @@ public: ++num_steps; done = (num_inconsistent_local_tr == 0); - if (!done && time_limit != 0 && t.elapsed() > time_limit) + if (!done && time_limit > 0. && t.elapsed() > time_limit) { #ifdef CGAL_TC_VERBOSE std::cerr << "Time limit reached." << std::endl; @@ -944,8 +948,11 @@ private: #endif // CGAL_LINKED_WITH_TBB void compute_tangent_triangulation( - std::size_t i, bool tangent_spaces_are_already_computed = false) + std::size_t i, bool tangent_spaces_are_already_computed = false, + bool verbose = false) { + if (verbose) + std::cerr << "** Computing tangent tri #" << i << " **" << std::endl; //std::cerr << "***********************************************" << std::endl; Triangulation &local_tr = m_triangulations[i].construct_triangulation(m_intrinsic_dimension); @@ -953,31 +960,19 @@ private: Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects - typename Kernel::Difference_of_points_d k_diff_pts = - m_k.difference_of_points_d_object(); typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); // Triangulation's traits functor & objects - typename Tr_traits::Squared_distance_d sqdist = - local_tr_traits.squared_distance_d_object(); typename Tr_traits::Point_weight_d point_weight = local_tr_traits.point_weight_d_object(); - typename Tr_traits::Point_drop_weight_d drop_w = - local_tr_traits.point_drop_weight_d_object(); /*typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object();*/ // CJTODO typename Get_functor::type power_center(local_tr_traits); -#ifdef CGAL_TC_PERTURB_POSITION // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions - const Point center_pt = k_transl(m_points[i], m_translations[i]); -#else - const Point ¢er_pt = m_points[i]; -#endif + const Point center_pt = compute_perturbed_point(i); // Estimate the tangent space if (!tangent_spaces_are_already_computed) @@ -1016,6 +1011,8 @@ private: ); center_vertex = local_tr.insert(wp); center_vertex->data() = i; + if (verbose) + std::cerr << "* Inserted point #" << i << std::endl; //const int NUM_NEIGHBORS = 150; //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); @@ -1025,7 +1022,7 @@ private: // of the sphere "star sphere" centered at "center_vertex" // and which contains all the // circumspheres of the star of "center_vertex" - boost::optional star_sphere_squared_radius; + boost::optional squared_star_sphere_radius_plus_margin; // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; @@ -1037,24 +1034,17 @@ private: // ith point = p, which is already inserted if (neighbor_point_idx != i) { -#ifdef CGAL_TC_PERTURB_POSITION - // No need to lock the mutex here since this will not be called while - // other threads are perturbing the positions - const Point neighbor_pt = k_transl( - m_points[neighbor_point_idx], m_translations[neighbor_point_idx]); -#else - const Point &neighbor_pt = m_points[neighbor_point_idx]; -#endif -#ifdef CGAL_TC_PERTURB_WEIGHT - FT neighbor_weight = m_weights[neighbor_point_idx]; -#else - FT neighbor_weight = 0; -#endif + // No need to lock the Mutex_for_perturb here since this will not be + // called while other threads are perturbing the positions + Point neighbor_pt; + FT neighbor_weight; + compute_perturbed_weighted_point( + neighbor_point_idx, neighbor_pt, neighbor_weight); // "4*m_sq_half_sparsity" because both points can be perturbed - if (star_sphere_squared_radius + if (squared_star_sphere_radius_plus_margin && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*m_sq_half_sparsity) + > *squared_star_sphere_radius_plus_margin) break; Tr_point proj_pt = project_point_and_compute_weight( @@ -1065,18 +1055,15 @@ private: //Tr_vertex_handle vh = local_tr.insert(proj_pt); if (vh != Tr_vertex_handle()) { - // CJTODO TEMP TEST - /*if (star_sphere_squared_radius - && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*m_sq_half_sparsity) - std::cout << "ARGGGGGGGH" << std::endl;*/ + if (verbose) + std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; vh->data() = neighbor_point_idx; - // Let's recompute star_sphere_squared_radius + // Let's recompute squared_star_sphere_radius_plus_margin if (local_tr.current_dimension() >= m_intrinsic_dimension) { - star_sphere_squared_radius = 0; + squared_star_sphere_radius_plus_margin = boost::none; // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; local_tr.incident_full_cells( @@ -1088,7 +1075,7 @@ private: Tr_full_cell_handle cell = *cit; if (local_tr.is_infinite(cell)) { - star_sphere_squared_radius = boost::none; + squared_star_sphere_radius_plus_margin = boost::none; break; } else @@ -1101,16 +1088,24 @@ private: FT sq_power_sphere_diam = 4*point_weight(c); - if (!star_sphere_squared_radius - || sq_power_sphere_diam > *star_sphere_squared_radius) + if (!squared_star_sphere_radius_plus_margin + || sq_power_sphere_diam > + *squared_star_sphere_radius_plus_margin) { - star_sphere_squared_radius = sq_power_sphere_diam; + squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; } } } + + // Let's add the margin, now + if (squared_star_sphere_radius_plus_margin) + { + squared_star_sphere_radius_plus_margin = CGAL::square( + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + + 2*m_half_sparsity); + } } } - //std::cerr << star_sphere_squared_radius << std::endl; } } @@ -1118,8 +1113,8 @@ private: // Update the associated star (in m_stars) //*************************************************** Star &star = m_stars[i]; - int cur_dim_plus_1 = local_tr.current_dimension() + 1; star.clear(); + int cur_dim_plus_1 = local_tr.current_dimension() + 1; std::vector incident_cells; local_tr.incident_full_cells( @@ -1270,6 +1265,51 @@ private: */ } + Point compute_perturbed_point(std::size_t pt_idx) + { +#ifdef CGAL_TC_PERTURB_POSITION + return m_k.translated_point_d_object()( + m_points[pt_idx], m_translations[pt_idx]); +#else + return m_points[pt_idx]; +#endif + } + + void compute_perturbed_weighted_point(std::size_t pt_idx, Point &p, FT &w) + { +#ifdef CGAL_TC_PERTURB_POSITION + p = m_k.translated_point_d_object()( + m_points[pt_idx], m_translations[pt_idx]); +#else + p = m_points[pt_idx]; +#endif +#ifdef CGAL_TC_PERTURB_WEIGHT + w = m_weights[pt_idx]; +#else + w = 0; +#endif + } + + Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) + { + typename Kernel::Construct_weighted_point_d k_constr_wp = + m_k.construct_weighted_point_d_object(); + + Weighted_point wp = k_constr_wp( +#ifdef CGAL_TC_PERTURB_POSITION + m_k.translated_point_d_object()(m_points[pt_idx], m_translations[pt_idx]), +#else + m_points[pt_idx], +#endif +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[pt_idx]); +#else + 0); +#endif + + return wp; + } + Point unproject_point(const Tr_point &p, const Point &origin, const Tangent_space_basis &tsb, const Tr_traits &tr_traits) @@ -1318,6 +1358,18 @@ private: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p + Tr_point project_point_and_compute_weight( + const Weighted_point &wp, const Point &origin, const Tangent_space_basis &ts, + const Tr_traits &tr_traits) const + { + typename Kernel::Point_drop_weight_d k_drop_w = + m_k.point_drop_weight_d_object(); + typename Kernel::Point_weight_d k_point_weight = + m_k.point_weight_d_object(); + return project_point_and_compute_weight( + k_drop_w(wp), k_point_weight(wp), origin, ts, tr_traits); + } + Tr_point project_point_and_compute_weight( const Point &p, FT w, const Point &origin, const Tangent_space_basis &ts, const Tr_traits &tr_traits) const @@ -1392,19 +1444,7 @@ private: ic_to_find.erase(point_idx); // For each cell - bool found = false; - Star::const_iterator it_inc_simplex = star.begin(); - Star::const_iterator it_inc_simplex_end = star.end(); - for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) - { - if (*it_inc_simplex == ic_to_find) - { - found = true; - break; - } - } - - if (!found) + if (std::find(star.begin(), star.end(), ic_to_find) == star.end()) return false; } @@ -1730,7 +1770,8 @@ private: } std::ostream &export_vertices_to_off( - std::ostream & os, std::size_t &num_vertices) + std::ostream & os, std::size_t &num_vertices, + bool use_perturbed_points = false) { if (m_points.empty()) { @@ -1755,13 +1796,14 @@ private: typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); // For each point p - for ( ; it_p != it_p_end ; ++it_p) + for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) { + Point p = (use_perturbed_points ? compute_perturbed_point(i) : *it_p); for (int ii = 0 ; ii < N ; ++ii) { int i = 0; for ( ; i < num_coords ; ++i) - os << CGAL::to_double(coord(*it_p, i)) << " "; + os << CGAL::to_double(coord(p, i)) << " "; if (i == 2) os << "0"; @@ -1810,12 +1852,37 @@ private: // Solves one inconsistency // "inconsistent_simplex" must contain p_idx and q_idx + // "inconsistent_simplex" must be in star(p) but not in star(q) void solve_inconsistency_by_adding_higher_dimensional_simplices( std::size_t p_idx, std::size_t q_idx, const std::set &inconsistent_simplex) { + CGAL_assertion_code( + std::set inc_s_minus_p = inconsistent_simplex; + inc_s_minus_p.erase(p_idx); + std::set inc_s_minus_q = inconsistent_simplex; + inc_s_minus_q.erase(q_idx); + ); + CGAL_assertion(std::find(m_stars[p_idx].begin(), m_stars[p_idx].end(), + inc_s_minus_p) != m_stars[p_idx].end()); + CGAL_assertion(std::find(m_stars[q_idx].begin(), m_stars[q_idx].end(), + inc_s_minus_q) == m_stars[q_idx].end()); + + typename Kernel::Point_drop_weight_d k_drop_w = + m_k.point_drop_weight_d_object(); typename Kernel::Translated_point_d k_transl = m_k.translated_point_d_object(); + typename Kernel::Squared_distance_d k_sqdist = + m_k.squared_distance_d_object(); + typename Kernel::Difference_of_points_d k_diff_pts = + m_k.difference_of_points_d_object(); + typename Kernel::Scalar_product_d k_inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Construct_weighted_point_d k_constr_wp = + m_k.construct_weighted_point_d_object(); + //typename Kernel::Power_distance_d k_power_dist = + // m_k.power_distance_d_object(); // CJTODO + typename Get_functor::type k_power_dist(m_k); const Tr_traits &q_tr_traits = m_triangulations[q_idx].tr().geom_traits(); /*typename Tr_traits::Power_center_d power_center = @@ -1825,130 +1892,238 @@ private: q_tr_traits.point_weight_d_object(); //------------------------------------------------------------------------- - //1. Compute power_center(p'q'r') in Tp => cp - //------------------------------------------------------------------------- - // CJTODO - - //------------------------------------------------------------------------- + //1. Compute power_center(p'q'r1'r2'..ri') in Tp => Cp //2. Compute power_center(inconsistent_simplex projected in Tq) // => gives Cq and radius Rq // Rq is also the radius of the ambient sphere S whose center is Cq and // which goes through all the ambient points of "inconsistent_simplex" - //------------------------------------------------------------------------- - std::vector simplex_pts_in_Tq; + //------------------------------------------------------------------------ + std::vector simplex_pts_in_Tp, simplex_pts_in_Tq; + simplex_pts_in_Tp.reserve(inconsistent_simplex.size()); simplex_pts_in_Tq.reserve(inconsistent_simplex.size()); - -#ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions - const Point center_pt = k_transl(m_points[q_idx], m_translations[q_idx]); -#else - const Point ¢er_pt = m_points[q_idx]; -#endif + const Point pt_p = compute_perturbed_point(p_idx); + const Point pt_q = compute_perturbed_point(q_idx); std::set::const_iterator it_point_idx = inconsistent_simplex.begin(); std::set::const_iterator it_point_idx_end = inconsistent_simplex.end(); - // For each point p of the simplex, we reproject it onto the tangent + // For each point of the simplex, we reproject it onto the tangent // space. Could be optimized since it's already been computed before. for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { -#ifdef CGAL_TC_PERTURB_POSITION - // No need to lock the mutex here since this will not be called while - // other threads are perturbing the positions - const Point p = k_transl( - m_points[*it_point_idx], m_translations[*it_point_idx]); -#else - const Point &p = m_points[*it_point_idx]; -#endif -#ifdef CGAL_TC_PERTURB_WEIGHT - FT w = m_weights[*it_point_idx]; -#else - FT w = 0; -#endif + const Weighted_point wp = compute_perturbed_weighted_point(*it_point_idx); + // No need to lock the Mutex_for_perturb here since this will not be + // called while other threads are perturbing the positions + simplex_pts_in_Tp.push_back(project_point_and_compute_weight( + wp, pt_p, m_tangent_spaces[p_idx], q_tr_traits)); simplex_pts_in_Tq.push_back(project_point_and_compute_weight( - p, w, center_pt, m_tangent_spaces[q_idx], q_tr_traits)); + wp, pt_q, m_tangent_spaces[q_idx], q_tr_traits)); } + Tr_point Cp = tr_power_center( + simplex_pts_in_Tp.begin(), simplex_pts_in_Tp.end()); Tr_point Cq = tr_power_center( simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); - //std::cerr << "Cq weight: " << tr_point_weight(Cq) << std::endl; // CJTODO TEMP + FT circumsphere_sqradius_p = tr_point_weight(Cp); + FT circumsphere_sqradius_q = tr_point_weight(Cq); + FT squared_circumsphere_radius_q_plus_margin = CGAL::square( + CGAL::sqrt(circumsphere_sqradius_q) + 2*m_half_sparsity); - //------------------------------------------------------------------------- - //3. Find points t1, t2... (in ambient space) which are inside S - //------------------------------------------------------------------------- - - // CJTODO: on prend le point le plus proche pour l'instant, mais il - // faudra changer a (cf 4 5 6, ci dessous) - // Et aussi, il faudra utiliser Power_distance dans le cas o on perturbe - // avec des poids (on est dans l'espace ambiant, donc ce sont les seuls - // poids possibles). Il faut aussi ajouter une marge lors de la recherche - // ANN puis restester la distance avec le vrai point perturbe. - Point global_Cq = unproject_point(Cq, center_pt, - m_tangent_spaces[q_idx], q_tr_traits); - std::size_t inside_point_idx; - INS_range ins_range = m_points_ds.query_incremental_ANN(global_Cq); + Weighted_point global_Cp = k_constr_wp( + unproject_point(Cp, pt_p, m_tangent_spaces[p_idx], q_tr_traits), + circumsphere_sqradius_p); + + Weighted_point global_Cq = k_constr_wp( + unproject_point(Cq, pt_q, m_tangent_spaces[q_idx], q_tr_traits), + circumsphere_sqradius_q); + + + // CJTODO TEMP ==================== + /*{ + INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(global_Cp)); for (INS_iterator nn_it = ins_range.begin() ; nn_it != ins_range.end() ; ++nn_it) { + FT neighbor_sqdist = nn_it->second; + + //std::cerr << nn_it->first << " : " << neighbor_sqdist << " / "; // CJTODO TEMP + + // When we're sure we got all the potential points, break + //if (neighbor_sqdist > circumsphere_sqradius_p + m_sq_half_sparsity) + // break; + std::size_t neighbor_point_idx = nn_it->first; - if (inconsistent_simplex.find(neighbor_point_idx) == - inconsistent_simplex.end()) + FT point_to_Cp_power_sqdist = k_power_dist( + global_Cp, compute_perturbed_weighted_point(neighbor_point_idx)); + //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP + // If the point is ACTUALLY "inside" S + if (point_to_Cp_power_sqdist <= FT(0) + && inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) { - inside_point_idx = neighbor_point_idx; - - { // CJTODO TEMP DEBUG - ++nn_it; - int count_insiders = 1; - for (int count = 0 ; count < inconsistent_simplex.size() ; ++count, ++nn_it) - { - std::size_t neighbor_point_idx = nn_it->first; - if (inconsistent_simplex.find(neighbor_point_idx) == - inconsistent_simplex.end()) - { - //std::cerr << "insider dist: " << nn_it->second << std::endl; // CJTODO TEMP - ++count_insiders; - } - else - { - //std::cerr << "Simplex point dist: " << nn_it->second << std::endl; // CJTODO TEMP - ++count; - } - } - - if (count_insiders > 1) - { - std::cerr << "Warning: " << count_insiders << " insiders in " - << inconsistent_simplex.size() - 1 << " simplex\n"; - } - //else - // std::cerr << "Ok: only one vertex inside the sphere\n"; - - } // END CJTODO - - break; + std::cerr << "Warning: " << neighbor_point_idx << " is inside Cp with power dist " << point_to_Cp_power_sqdist << "\n"; } } + }*/ + // /CJTODO ==================== - //std::size_t inside_point_idx = kns_range.begin()->first; - //------------------------------------------------------------------------- - //4. S'il n'y a qu'un seul points ti, passer la dernire tape + //3. Find points t1, t2... (in ambient space) which are inside S //------------------------------------------------------------------------- + std::vector inside_pt_indices; + INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(global_Cq)); + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { + FT neighbor_sqdist = nn_it->second; + + // When we're sure we got all the potential points, break + if (neighbor_sqdist > squared_circumsphere_radius_q_plus_margin) + break; + + std::size_t neighbor_point_idx = nn_it->first; + FT point_to_Cq_power_sqdist = k_power_dist( + global_Cq, compute_perturbed_weighted_point(neighbor_point_idx)); + // If the point is ACTUALLY "inside" S + if (point_to_Cq_power_sqdist <= FT(0) + && inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) + { + inside_pt_indices.push_back(neighbor_point_idx); + } + // CJTODO TEMP: + /*{ + typename Tr_traits::Power_test_d side = q_tr_traits.power_test_d_object(); + typename Tr_traits::Orientation_d orient = q_tr_traits.orientation_d_object(); + Orientation o = orient(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); + auto p = project_point_and_compute_weight( + compute_perturbed_weighted_point(neighbor_point_idx), + pt_q, m_tangent_spaces[q_idx], q_tr_traits); + auto sid = (o == NEGATIVE ? + side(simplex_pts_in_Tq.rbegin(), simplex_pts_in_Tq.rend(), p) + : side(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end(), p)); + switch(sid) + { + case ON_NEGATIVE_SIDE: + std::cerr << "ON_NEGATIVE_SIDE" << std::endl; // CJTODO TEMP + break; + case ON_POSITIVE_SIDE: + std::cerr << "ON_POSITIVE_SIDE" << std::endl; // CJTODO TEMP + break; + case ON_ORIENTED_BOUNDARY: + std::cerr << "ON_ORIENTED_BOUNDARY" << std::endl; // CJTODO TEMP + break; + } + }*/ + } + CGAL_assertion_msg(!inside_pt_indices.empty(), + "There should be at least one vertex inside the sphere"); + // CJTODO TEMP DEBUG + /*if (inside_pt_indices.empty()) + { + //compute_tangent_triangulation(q_idx, true, true); + std::cerr << "Error: inside_pt_indices.empty()\n"; + std::cerr << "Stars:\n"; + for (auto s : m_stars[q_idx]) + { + std::cerr << q_idx << " "; + std::copy(s.begin(), s.end(), + std::ostream_iterator(std::cerr, " ")); + std::cerr << std::endl; + } + std::cerr << std::endl; + }*/ + // CJTODO TEMP DEBUG + if (inside_pt_indices.size() > 1) + { + std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " + << inconsistent_simplex.size() - 1 << " simplex\n"; + } + //------------------------------------------------------------------------- - //5. Pour chaque ti, calculer la sphre qui passe par p, q, r, ti dont le centre est sur la droite (cq, cq) + //4. If there's more than one ti... or not //------------------------------------------------------------------------- - + // CJTODO: take weights into account + std::size_t inside_point_idx; + if (inside_pt_indices.size() > 1) + { + //----------------------------------------------------------------------- + //5. For each ti, compute the sphere that goes through + // p, q, r1, r2..., ri and ti whose center is on (cp, cq) + // We're looking for a point on (Cp, Cq) at equal distance from p and + // ti. + // The center of the sphere is then: Cp + a(Cq - Cp) + // where a = (sqdist(Cp,ti) - sqdist(Cp,p)) / (2*(Cq-Cp).(ti-p)) + //6. Keep point ti such as dist(cp, ci) is the smallest + //----------------------------------------------------------------------- + + FT min_a = std::numeric_limits::max(); + for (auto idx : inside_pt_indices) // CJTODO: C++11 + { + const Point ti = compute_perturbed_point(idx); + const Point &cp = k_drop_w(global_Cp); + const Point &cq = k_drop_w(global_Cq); + FT a = + (k_sqdist(cp, ti) - k_sqdist(cp, pt_p)) / + (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); + + if (a < min_a) + { + min_a = a; + inside_point_idx = idx; + } + } + + // CJTODO TEMP ==================== + /*{ + typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + typename Kernel::Point_weight_d k_weight = m_k.point_weight_d_object(); + Weighted_point C = k_constr_wp( + k_transl(k_drop_w(global_Cp), scaled_vec(k_diff_pts(k_drop_w(global_Cq), k_drop_w(global_Cp)), min_a)), + k_sqdist(k_transl(k_drop_w(global_Cp), scaled_vec(k_diff_pts(k_drop_w(global_Cq), k_drop_w(global_Cp)), min_a)), pt_p)); + INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(C)); + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { + FT neighbor_sqdist = nn_it->second; + + //std::cerr << nn_it->first << " : " << neighbor_sqdist << " / "; // CJTODO TEMP + + // When we're sure we got all the potential points, break + if (neighbor_sqdist > k_weight(C) + m_sq_half_sparsity) + break; + + std::size_t neighbor_point_idx = nn_it->first; + FT point_to_C_power_sqdist = + k_power_dist(C, compute_perturbed_weighted_point(neighbor_point_idx)); + //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP + // If the point is ACTUALLY "inside" S + if (point_to_C_power_sqdist <= FT(-0.000001) + && inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) + { + std::cerr << "Warning: " << neighbor_point_idx << " is inside C with power dist " << point_to_C_power_sqdist << "\n"; + } + } + }*/ + // /CJTODO ==================== + } + else + { + inside_point_idx = *inside_pt_indices.begin(); + } + //------------------------------------------------------------------------- - //6. Conserver le point ti tel que dist(cp, ci) soit la plus petite - //------------------------------------------------------------------------- - - //------------------------------------------------------------------------- - //7. Crer un k+1-simplex (inconsistent_simplex, ti) + //7. Create a k+1-simplex (inconsistent_simplex, ti) //------------------------------------------------------------------------- std::set new_simplex = inconsistent_simplex; new_simplex.insert(inside_point_idx); @@ -1967,6 +2142,7 @@ private: // Test and solve inconsistencies of a simplex. // Returns true if some inconsistencies were found. + // Precondition: incident_simplex is in the star of m_points[tr_index] bool check_and_solve_inconsistencies_by_adding_higher_dim_simplices( std::size_t tr_index, const std::set &incident_simplex) { @@ -1981,10 +2157,10 @@ private: simplex.insert(tr_index); // Check if the simplex is in the stars of all its vertices - std::set::const_iterator it_point_idx = simplex.begin(); + std::set::const_iterator it_point_idx = incident_simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p // and we check if "simplex" is among them - for ( ; it_point_idx != simplex.end() ; ++it_point_idx) + for ( ; it_point_idx != incident_simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; @@ -1994,20 +2170,7 @@ private: Incident_simplex ic_to_find = simplex; ic_to_find.erase(point_idx); - // For each cell - bool found = false; - Star::const_iterator it_inc_simplex = star.begin(); - Star::const_iterator it_inc_simplex_end = star.end(); - for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) - { - if (*it_inc_simplex == ic_to_find) - { - found = true; - break; - } - } - - if (!found) + if (std::find(star.begin(), star.end(), ic_to_find) == star.end()) { solve_inconsistency_by_adding_higher_dimensional_simplices( tr_index, *it_point_idx, simplex); From cd4d1a3fa80fec425158285aff8cd5ea86f71c58 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 16:02:46 +0100 Subject: [PATCH 231/487] Added timers --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index b8f795ceea5..a82f0cb1caf 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -225,16 +225,18 @@ void make_tc(std::vector &points, int intrinsic_dim, export_after_fix_time = t.elapsed(); t.reset(); } + t.reset(); // Try to solve the remaining inconstencies tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + double fix2_time = t.elapsed(); t.reset(); TC::Simplicial_complex complex; int max_dim = tc.export_TC(complex, false); std::set > not_delaunay_simplices; - if (ambient_dim <= 4) + /*if (ambient_dim <= 4) { tc.check_if_all_simplices_are_in_the_ambient_delaunay( &complex, true, ¬_delaunay_simplices); - } + }*/ double export_after_fix2_time = -1.; if (intrinsic_dim <= 3) @@ -277,6 +279,7 @@ void make_tc(std::vector &points, int intrinsic_dim, << " * Fix inconsistencies: " << fix_time << " (" << num_fix_steps << " steps) ==> " << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl + << " * Fix 2: " << fix2_time << std::endl << " * Export to OFF (after fix): " << export_after_fix_time << std::endl << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl << " * Export to OFF (after collapse): " From c3a7c297629c94bd7be6046ac1378b3d9df1073c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 16:17:38 +0100 Subject: [PATCH 232/487] Updated script + config file --- .../Tangential_complex/benchmark_script.txt | 28 ++++++++++++------- .../include/CGAL/Tangential_complex/config.h | 4 +-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index ffcaec285e8..17d30966cbe 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -3,21 +3,29 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- #---------------------------------------------------------- Very small cases for Debug mode ------------------------------------------------------------- -#generate_sphere_d 3 - - 20 3 2 0.05 3000 1 -#generate_klein_bottle_4D 4 3 - 20 4 2 1.5 3000 1 +#generate_sphere_d 3 - - 20 3 2 0.05 1 1 +#generate_klein_bottle_4D 4 3 - 70 4 2 1.5 1 1 #------------------------------------------------------------------ From files --------------------------------------------------------------------------- #data/SO3_50000.txt - - - 0 9 3 0.2 3000 1 -data/SO3_10000.txt - - - 0 9 3 0.05 3000 1 +#data/SO3_10000.txt - - - 0 9 3 0.05 10 1 #data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 3000 1 #data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 3000 1 #data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 3000 1 -#data/Cy8.txt - - - 0 24 2 0.1 3000 1 +#data/Cy8.txt - - - 0 24 2 0.1 2 1 #data/Kl.txt - - - 0 5 2 0.05 3000 1 #data/S3.txt - - - 0 4 3 0.05 3000 1 -#data/buddha_100kv.txt - - - 0 3 2 0.005 3000 1 -#data/fandisk.txt - - - 0 3 2 0.01 3000 1 -#data/fertility.txt - - - 0 3 2 0.1 600 1 + +#---------------------------------------------------------------------- 3D meshes ------------------------------------------------------------------------ +#data/buddha_100kv.txt - - - 0 3 2 0.005 10 1 +data/fandisk.txt - - - 0 3 2 0.01 100 1 +#data/fertility.txt - - - 0 3 2 0.4 120 1 +#data/bunny.txt - - - 0 3 2 0.5 5 1 +#data/blob.txt - - - 0 3 2 0.01 10 1 +#data/3holes.txt - - - 0 3 2 0.01 10 1 +#data/785_hand_2500v.txt - - - 0 3 2 0.01 10 1 +#data/785_hand_50kv.txt - - - 0 3 2 0.01 10 1 +#data/bumpy_sphere.txt - - - 0 3 2 0.01 10 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ #generate_sphere_d 3 - - 4 3 2 0.05 3000 1 @@ -26,9 +34,9 @@ data/SO3_10000.txt - - - 0 9 3 0.05 3000 1 #generate_sphere_d 3 - - 30000 4 3 0.05 3000 1 #generate_plane - - - 30000 3 2 0.005 3000 1 #generate_moment_curve 0 1 - 30000 6 1 0.005 3000 1 -#generate_klein_bottle_4D 4 3 - 10000 4 2 1.5 3000 1 +#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 10 1 #generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 3000 1 #----------------------------------------------------------- Performance testing ------------------------------------------------------------------------- -# TC: 5.55 / 1st fix step : 2.7 -data/fertility.txt - - - 0 3 2 0.1 600 1 \ No newline at end of file +# TC: 5.55 / 1st fix step : 0.2 +#data/fertility.txt - - - 0 3 2 0.1 10 1 \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 47bf0147c91..f9339340dbe 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -58,10 +58,10 @@ // for local tri where there are some inconsistencies // But be careful: refreshing the TC may invalidate cells, so the // incident cells have to be recomputed again -//#define CGAL_TC_PERTURB_POSITION +#define CGAL_TC_PERTURB_POSITION # define CGAL_TC_PERTURB_POSITION_TANGENTIAL // default //# define CGAL_TC_PERTURB_POSITION_GLOBAL -#define CGAL_TC_PERTURB_WEIGHT +//#define CGAL_TC_PERTURB_WEIGHT //#define CGAL_TC_PERTURB_TANGENT_SPACE //========================= Parameters ======================================== From 7357337195097f820f64505e8c8fad827ee9b79b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 16:41:46 +0100 Subject: [PATCH 233/487] Added a TODO --- Tangential_complex/include/CGAL/Tangential_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 53d557d4d73..bff9c3e3b06 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1998,7 +1998,7 @@ private: { inside_pt_indices.push_back(neighbor_point_idx); } - // CJTODO TEMP: + // CJTODO: use this instead of point_to_Cq_power_sqdist? /*{ typename Tr_traits::Power_test_d side = q_tr_traits.power_test_d_object(); typename Tr_traits::Orientation_d orient = q_tr_traits.orientation_d_object(); From 16279ad6312a4bec51f554a880f2fa5a7cae5f33 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Mar 2015 15:43:22 +0100 Subject: [PATCH 234/487] Refined margin computation + Use Power_center_d and Power_distance_d --- .../include/CGAL/Tangential_complex.h | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index bff9c3e3b06..e307fa4c72b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -636,7 +636,7 @@ public: void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() { - // CJTODO: parallel_for + // CJTODO: parallel_for??? for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) { bool inconsistencies_found; @@ -966,9 +966,8 @@ private: // Triangulation's traits functor & objects typename Tr_traits::Point_weight_d point_weight = local_tr_traits.point_weight_d_object(); - /*typename Tr_traits::Power_center_d power_center = - local_tr_traits.power_center_d_object();*/ // CJTODO - typename Get_functor::type power_center(local_tr_traits); + typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object(); // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions @@ -1098,11 +1097,17 @@ private: } // Let's add the margin, now + // The value depends on whether we perturb weight or position if (squared_star_sphere_radius_plus_margin) { +#ifdef CGAL_TC_PERTURB_WEIGHT + squared_star_sphere_radius_plus_margin = + *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; +#else squared_star_sphere_radius_plus_margin = CGAL::square( CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2*m_half_sparsity); +#endif } } } @@ -1700,9 +1705,8 @@ private: local_tr_traits)); } - //typename Tr_traits::Power_center_d power_center = - // local_tr_traits.power_center_d_object(); // CJTODO - typename Get_functor::type power_center(local_tr_traits); + typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object(); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); @@ -1880,14 +1884,12 @@ private: m_k.scalar_product_d_object(); typename Kernel::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); - //typename Kernel::Power_distance_d k_power_dist = - // m_k.power_distance_d_object(); // CJTODO - typename Get_functor::type k_power_dist(m_k); + typename Kernel::Power_distance_d k_power_dist = + m_k.power_distance_d_object(); const Tr_traits &q_tr_traits = m_triangulations[q_idx].tr().geom_traits(); - /*typename Tr_traits::Power_center_d power_center = - local_tr_traits.power_center_d_object();*/ // CJTODO - typename Get_functor::type tr_power_center(q_tr_traits); + typename Tr_traits::Power_center_d tr_power_center = + q_tr_traits.power_center_d_object(); typename Tr_traits::Point_weight_d tr_point_weight = q_tr_traits.point_weight_d_object(); From 8ad1b81323ceeadb0c3eab7804cb3b0e1e452b87 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Mar 2015 16:54:23 +0100 Subject: [PATCH 235/487] Now taking weights into account for the computation of "min_a" --- .../include/CGAL/Tangential_complex.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index e307fa4c72b..d1f83fcb601 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1933,8 +1933,13 @@ private: FT circumsphere_sqradius_p = tr_point_weight(Cp); FT circumsphere_sqradius_q = tr_point_weight(Cq); +#ifdef CGAL_TC_PERTURB_WEIGHT + FT squared_circumsphere_radius_q_plus_margin = + circumsphere_sqradius_q + 4*m_sq_half_sparsity; +#else FT squared_circumsphere_radius_q_plus_margin = CGAL::square( CGAL::sqrt(circumsphere_sqradius_q) + 2*m_half_sparsity); +#endif Weighted_point global_Cp = k_constr_wp( unproject_point(Cp, pt_p, m_tangent_spaces[p_idx], q_tr_traits), @@ -2053,7 +2058,6 @@ private: //------------------------------------------------------------------------- //4. If there's more than one ti... or not //------------------------------------------------------------------------- - // CJTODO: take weights into account std::size_t inside_point_idx; if (inside_pt_indices.size() > 1) { @@ -2073,9 +2077,20 @@ private: const Point ti = compute_perturbed_point(idx); const Point &cp = k_drop_w(global_Cp); const Point &cq = k_drop_w(global_Cq); + +#ifdef CGAL_TC_PERTURB_WEIGHT + const Weighted_point ti_w = compute_perturbed_weighted_point(idx); + const Weighted_point p_w = compute_perturbed_weighted_point(p_idx); + const Weighted_point cp_w0 = k_constr_wp(k_drop_w(global_Cp), FT(0)); + const Weighted_point wp_w0 = k_constr_wp(k_drop_w(global_Cq), FT(0)); + FT a = + (k_power_dist(cp_w0, ti_w) - k_power_dist(cp_w0, p_w)) / + (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); +#else FT a = (k_sqdist(cp, ti) - k_sqdist(cp, pt_p)) / (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); +#endif if (a < min_a) { From 20f871174017420d530ec38a984292cbbb97ebc7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 9 Mar 2015 14:49:12 +0100 Subject: [PATCH 236/487] Remove useless function call --- Tangential_complex/include/CGAL/Tangential_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d1f83fcb601..42e1ea34b27 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -795,7 +795,7 @@ public: { Simplex simplex; for (int i = 0 ; i < dim + 1 ; ++i) - simplex.insert(cit.base()->vertex(combi[i])->data()); + simplex.insert(cit->vertex(combi[i])->data()); amb_dt_simplices.insert(simplex); } From 742b9d45e2bf43ef6ca2df80be91732d45bafa4f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 13 Mar 2015 11:07:26 +0100 Subject: [PATCH 237/487] Clarify comment --- .../include/CGAL/Tangential_complex/Simplicial_complex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 445864ceb67..3e304742f64 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -74,10 +74,10 @@ public: } // For each non-maximal k-face F, if F has only one maximal coface Cf: - // - Look for the other k-faces F2 of Cf in the map and: + // - Look for the other k-faces F2, F3... of Cf in the map and: // * if the list contains only Cf, clear the list (we don't remove the - // list since it was create troubles with the iterators) and add f2 - // to the complex + // list since it creates troubles with the iterators) and add the F2, + // F3... to the complex // * otherwise, remove Cf from the associated list // - Remove Cf from the complex for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(), From 672f3ac0c1f907a853f65b4dc591fd52013c061f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 13 Mar 2015 17:09:46 +0100 Subject: [PATCH 238/487] Bug fix: go one step further in the recursive call --- .../include/CGAL/Tangential_complex/Simplicial_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 3e304742f64..3ef449dfa9c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -95,6 +95,7 @@ public: combinations(*it_Cf, k + 1, std::back_inserter(k_faces)); for (const auto &f2 : k_faces) // CJTODO C++1 { + // Skip F if (f2 != it_map_elt->first) { Cofaces_map::iterator it_comb_in_map = cofaces_map.find(f2); @@ -119,7 +120,7 @@ public: } // Collapse the lower dimension simplices - if (k > 1) + if (k > 0) collapse(max_simplex_dim - 1); } From d23a39c740fa3defed525eb4f142916b367f7419 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Mar 2015 18:04:50 +0100 Subject: [PATCH 239/487] Added SC::is_pure_manifold --- .../Tangential_complex/benchmark_tc.cpp | 32 ++++++--- .../Tangential_complex/Simplicial_complex.h | 66 ++++++++++++++----- 2 files changed, 72 insertions(+), 26 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index a82f0cb1caf..308d3e950ad 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -91,9 +91,12 @@ protected: subelements.push_back("Final_num_inconsistent_local_tr"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); - subelements.push_back("Fix_successful"); - subelements.push_back("Fix_time"); - subelements.push_back("Fix_steps"); + subelements.push_back("Fix1_successful"); + subelements.push_back("Fix1_time"); + subelements.push_back("Fix1_steps"); + subelements.push_back("Fix2_pure_manifold"); + subelements.push_back("Fix2_num_wrong_number_of_cofaces"); + subelements.push_back("Fix2_time"); subelements.push_back("Info"); return subelements; @@ -264,22 +267,26 @@ void make_tc(std::vector &points, int intrinsic_dim, tc.export_to_off(complex, off_stream); export_after_collapse_time = t.elapsed(); t.reset(); } - + std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces; + bool pure_manifold = complex.is_pure_manifold( + intrinsic_dim, false, 0, + &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); complex.display_stats(); std::cerr << std::endl << "================================================" << std::endl << "Number of vertices: " << tc.number_of_vertices() << std::endl + << "Pure manifold: " << (pure_manifold ? "YES" : "NO") << std::endl << "Computation times (seconds): " << std::endl << " * Tangential complex: " << init_time + computation_time << std::endl << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl << " * Export to OFF (before fix): " << export_before_time << std::endl - << " * Fix inconsistencies: " << fix_time + << " * Fix inconsistencies 1: " << fix_time << " (" << num_fix_steps << " steps) ==> " << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl - << " * Fix 2: " << fix2_time << std::endl + << " * Fix inconsistencies 2: " << fix2_time << std::endl << " * Export to OFF (after fix): " << export_after_fix_time << std::endl << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl << " * Export to OFF (after collapse): " @@ -289,10 +296,15 @@ void make_tc(std::vector &points, int intrinsic_dim, CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); - CGAL_TC_SET_PERFORMANCE_DATA("Fix_successful", - (fix_ret == CGAL::TC_FIXED ? "Y" : "N")); - CGAL_TC_SET_PERFORMANCE_DATA("Fix_time", fix_time); - CGAL_TC_SET_PERFORMANCE_DATA("Fix_steps", num_fix_steps); + CGAL_TC_SET_PERFORMANCE_DATA("Fix1_successful", + (fix_ret == CGAL::TC_FIXED ? "Y" : "N")); + CGAL_TC_SET_PERFORMANCE_DATA("Fix1_time", fix_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix1_steps", num_fix_steps); + CGAL_TC_SET_PERFORMANCE_DATA("Fix2_pure_manifold", + (pure_manifold ? "Y" : "N")); + CGAL_TC_SET_PERFORMANCE_DATA("Fix2_num_wrong_number_of_cofaces", + num_wrong_number_of_cofaces); + CGAL_TC_SET_PERFORMANCE_DATA("Fix2_time", fix2_time); CGAL_TC_SET_PERFORMANCE_DATA("Info", ""); } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 3ef449dfa9c..e386739020f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -160,14 +160,19 @@ public: std::cerr << "==========================================================\n"; } - // CJTODO: this is only based on the fact that each edge should have two - // cofaces - bool is_manifold(bool exit_at_the_first_problem = true) + // verbose_level = 0, 1 or 2 + bool is_pure_manifold(int simplex_dim, + bool exit_at_the_first_problem = false, + int verbose_level = 0, + std::size_t *p_num_wrong_dim_simplices = NULL, + std::size_t *p_num_wrong_number_of_cofaces = NULL) { - typedef std::set Edge; - typedef std::map Cofaces_map; + typedef std::set K_1_face; + typedef std::map Cofaces_map; - // Counts the number of cofaces of each edge + std::size_t num_wrong_dim_simplices = 0, num_wrong_number_of_cofaces = 0; + + // Counts the number of cofaces of each K_1_face // Create a map associating each non-maximal k-faces to the list of its // maximal cofaces @@ -177,19 +182,26 @@ public: it_simplex != it_simplex_end ; ++it_simplex) { - if (it_simplex->size() > 2) + if (it_simplex->size() != simplex_dim + 1) { - std::vector edges; - // Get the k-faces composing the simplex - combinations(*it_simplex, 2, std::back_inserter(edges)); - for (const auto &edge : edges) // CJTODO C++1 + if (verbose_level >= 2) + std::cerr << "Found a simplex with dim = " + << it_simplex->size() - 1 << std::endl; + ++num_wrong_dim_simplices; + } + else + { + std::vector k_1_faces; + // Get the facets composing the simplex + combinations( + *it_simplex, simplex_dim, std::back_inserter(k_1_faces)); + for (const auto &k_1_face : k_1_faces) // CJTODO C++1 { - ++cofaces_map[edge]; + ++cofaces_map[k_1_face]; } } } - bool manifold = true; for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(), it_map_end = cofaces_map.end() ; it_map_elt != it_map_end ; @@ -197,15 +209,37 @@ public: { if (it_map_elt->second != 2) { - std::cerr << "Found an edge with " << it_map_elt->second << " cofaces\n"; + if (verbose_level >= 2) + std::cerr << "Found a k-1-face with " + << it_map_elt->second << " cofaces\n"; + if (exit_at_the_first_problem) return false; else - manifold = false; + ++num_wrong_number_of_cofaces; } } - return manifold; + bool ret = num_wrong_dim_simplices == 0 && num_wrong_number_of_cofaces == 0; + + if (verbose_level >= 1) + { + std::cerr << "is_pure_manifold: " << (ret ? "YES" : "NO") << std::endl; + if (!ret) + { + std::cerr << " * Number of wrong dimension simplices: " + << num_wrong_dim_simplices << std::endl + << " * Number of wrong number of cofaces: " + << num_wrong_number_of_cofaces << std::endl; + } + } + + if (p_num_wrong_dim_simplices) + *p_num_wrong_dim_simplices = num_wrong_dim_simplices; + if (p_num_wrong_number_of_cofaces) + *p_num_wrong_number_of_cofaces = num_wrong_number_of_cofaces; + + return ret; } private: From cbc108171b7224576e56dfa93b661b3af20f9ed9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Mar 2015 18:05:10 +0100 Subject: [PATCH 240/487] Updated script and config --- .../Tangential_complex/benchmark_script.txt | 40 +++++++++---------- .../include/CGAL/Tangential_complex/config.h | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 17d30966cbe..0aa065fd7a8 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -3,29 +3,29 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- #---------------------------------------------------------- Very small cases for Debug mode ------------------------------------------------------------- -#generate_sphere_d 3 - - 20 3 2 0.05 1 1 -#generate_klein_bottle_4D 4 3 - 70 4 2 1.5 1 1 +#generate_sphere_d 3 - - 20 3 2 0.05 60 1 +#generate_klein_bottle_4D 4 3 - 70 4 2 1.5 60 1 #------------------------------------------------------------------ From files --------------------------------------------------------------------------- -#data/SO3_50000.txt - - - 0 9 3 0.2 3000 1 -#data/SO3_10000.txt - - - 0 9 3 0.05 10 1 +data/SO3_50000.txt - - - 0 9 3 0.2 60 1 +data/SO3_10000.txt - - - 0 9 3 0.05 60 1 #data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 3000 1 #data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 3000 1 #data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 3000 1 -#data/Cy8.txt - - - 0 24 2 0.1 2 1 -#data/Kl.txt - - - 0 5 2 0.05 3000 1 -#data/S3.txt - - - 0 4 3 0.05 3000 1 +data/Cy8.txt - - - 0 24 2 0.1 60 1 +data/Kl.txt - - - 0 5 2 0.05 60 1 +data/S3.txt - - - 0 4 3 0.05 60 1 #---------------------------------------------------------------------- 3D meshes ------------------------------------------------------------------------ -#data/buddha_100kv.txt - - - 0 3 2 0.005 10 1 -data/fandisk.txt - - - 0 3 2 0.01 100 1 -#data/fertility.txt - - - 0 3 2 0.4 120 1 -#data/bunny.txt - - - 0 3 2 0.5 5 1 -#data/blob.txt - - - 0 3 2 0.01 10 1 -#data/3holes.txt - - - 0 3 2 0.01 10 1 -#data/785_hand_2500v.txt - - - 0 3 2 0.01 10 1 -#data/785_hand_50kv.txt - - - 0 3 2 0.01 10 1 -#data/bumpy_sphere.txt - - - 0 3 2 0.01 10 1 +data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 +data/fandisk.txt - - - 0 3 2 0.01 60 1 +data/fertility.txt - - - 0 3 2 0.4 60 1 +data/bunny.txt - - - 0 3 2 0.5 60 1 +data/blob.txt - - - 0 3 2 0.01 60 1 +data/3holes.txt - - - 0 3 2 0.01 60 1 +data/785_hand_2500v.txt - - - 0 3 2 0.01 60 1 +data/785_hand_50kv.txt - - - 0 3 2 0.01 60 1 +data/bumpy_sphere.txt - - - 0 3 2 0.01 60 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ #generate_sphere_d 3 - - 4 3 2 0.05 3000 1 @@ -33,10 +33,10 @@ data/fandisk.txt - - - 0 3 2 0.01 100 1 #generate_sphere_d 3 - - 30000 3 2 0.005 3000 1 #generate_sphere_d 3 - - 30000 4 3 0.05 3000 1 #generate_plane - - - 30000 3 2 0.005 3000 1 -#generate_moment_curve 0 1 - 30000 6 1 0.005 3000 1 -#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 10 1 -#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 3000 1 +generate_moment_curve 0 1 - 30000 6 1 0.005 60 1 +generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 60 1 +generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 #----------------------------------------------------------- Performance testing ------------------------------------------------------------------------- # TC: 5.55 / 1st fix step : 0.2 -#data/fertility.txt - - - 0 3 2 0.1 10 1 \ No newline at end of file +#data/fertility.txt - - - 0 3 2 0.1 100 1 \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index f9339340dbe..1ba33d4eead 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -41,7 +41,7 @@ //#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY //#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY //#define CGAL_TC_PERTURB_THE_1_STAR -#define CGAL_TC_PERTURB_N_CLOSEST_POINTS // perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS closest points +#define CGAL_TC_PERTURB_N_CLOSEST_POINTS // perturb the CGAL_TC_NUMBER_OF_PERTURBED_POINTS closest points // Otherwise, perturb one random point of the simplex // Only used if CGAL_TC_PERTURB_N_CLOSEST_POINTS is defined From a9c14b20091f504618e08db06959b287ed25f45f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 13 Apr 2015 16:42:23 +0200 Subject: [PATCH 241/487] Added normalize_vector --- .../CGAL/Tangential_complex/utilities.h | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index a15c38f13f8..64e8c4ddfc2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -113,22 +113,33 @@ namespace Tangential_complex_ { } };*/ + + + template + std::vector + normalize_vector( + std::vector &v, + K const& k) + { + v = k.scaled_vector_d_object()( + v, FT(1)/CGAL::sqrt(k.squared_length_d_object()(v))); + } template std::vector compute_gram_schmidt_basis( std::vector const& input_basis, - K const& kernel) + K const& k) { typedef typename K::FT FT; typedef typename K::Vector_d Vector; typedef std::vector Basis; // Kernel functors - typename K::Squared_length_d sqlen = kernel.squared_length_d_object(); - typename K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); - typename K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); - typename K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); + typename K::Squared_length_d sqlen = k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = k.scaled_vector_d_object(); + typename K::Scalar_product_d inner_pdct = k.scalar_product_d_object(); + typename K::Difference_of_vectors_d diff_vec = k.difference_of_vectors_d_object(); Basis output_basis; @@ -146,8 +157,7 @@ namespace Tangential_complex_ { u = diff_vec(u, u_proj); } - output_basis.push_back( - scaled_vec(u, FT(1)/CGAL::sqrt(sqlen(u)))); + output_basis.push_back(normalize_vector(u, k)); } return output_basis; From d1a1ec164de7d7ecbfe4ac41673a59bbd2ea87ef Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 13 Apr 2015 16:45:46 +0200 Subject: [PATCH 242/487] Added the ability to compute the orthogonal space basis --- .../include/CGAL/Tangential_complex.h | 113 +++++++++++------- 1 file changed, 73 insertions(+), 40 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 42e1ea34b27..ce7b916a950 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -68,6 +68,7 @@ //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) + namespace CGAL { using namespace Tangential_complex_; @@ -124,6 +125,7 @@ class Tangential_complex typedef typename Tr_traits::Vector_d Tr_vector; typedef std::vector Tangent_space_basis; + typedef std::vector Orthogonal_space_basis; typedef std::vector Points; typedef std::vector Weights; @@ -180,20 +182,21 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; - typedef typename std::vector TS_container; - typedef typename std::vector Tr_container; - typedef typename std::vector Vectors; + typedef typename std::vector TS_container; + typedef typename std::vector OS_container; + typedef typename std::vector Tr_container; + typedef typename std::vector Vectors; // An Incident_simplex is the list of the verter indices // except the center vertex - typedef std::set Incident_simplex; - typedef std::vector Star; - typedef std::vector Stars_container; + typedef std::set Incident_simplex; + typedef std::vector Star; + typedef std::vector Stars_container; #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - //typedef tbb::queuing_mutex Tr_mutex; + //typedef tbb::queuing_mutex Tr_mutex; #endif // For transform_iterator @@ -261,6 +264,9 @@ public: //m_tr_mutexes.resize(m_points.size()); #endif m_tangent_spaces.resize(m_points.size()); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_orth_spaces.resize(m_points.size()); +#endif #ifdef CGAL_TC_PERTURB_WEIGHT m_weights.resize(m_points.size(), FT(0)); #endif @@ -275,10 +281,6 @@ public: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE m_perturb_tangent_space.resize(m_points.size(), false); #endif -#ifdef CGAL_TC_EXPORT_NORMALS - m_normals.resize(m_points.size(), - m_k.construct_vector_d_object()(m_ambiant_dim)); -#endif #ifdef CGAL_LINKED_WITH_TBB // Parallel @@ -976,8 +978,9 @@ private: // Estimate the tangent space if (!tangent_spaces_are_already_computed) { -#ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i]); #else m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif @@ -985,10 +988,11 @@ private: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { -#ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt,&m_normals[i],true); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt, true); + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); #endif m_perturb_tangent_space[i] = false; } @@ -1151,14 +1155,14 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } - Tangent_space_basis compute_tangent_space(const Point &p -#ifdef CGAL_TC_EXPORT_NORMALS - , Vector *p_normal -#endif + Tangent_space_basis compute_tangent_space( + const Point &p + , bool normalize_basis = true + , Orthogonal_space_basis *p_orth_space_basis = NULL #ifdef CGAL_TC_PERTURB_TANGENT_SPACE - , bool perturb = false + , bool perturb = false #endif - ) const + ) const { //******************************* PCA ************************************* @@ -1216,17 +1220,44 @@ private: i >= m_ambiant_dim - m_intrinsic_dimension ; --i) { - ts.push_back(constr_vec( - m_ambiant_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim)); + if (normalize_basis) + { + ts.push_back(normalize_vector(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim))); + } + else + { + ts.push_back(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim)); + } + } + + if (p_orth_space_basis) + { + for (int i = m_ambiant_dim - m_intrinsic_dimension - 1 ; + i >= 0 ; + --i) + { + if (normalize_basis) + { + p_orth_space_basis->push_back(normalize_vector(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim))); + } + else + { + p_orth_space_basis->push_back(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim)); + } + } } -#ifdef CGAL_TC_EXPORT_NORMALS - *p_normal = constr_vec( - m_ambiant_dim, - eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data(), - eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data() + m_ambiant_dim); -#endif //************************************************************************* @@ -1234,7 +1265,9 @@ private: //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; - return compute_gram_schmidt_basis(ts, m_k); + // CJTODO: les vecteurs sont dj orthogonaux, a priori ! A VERIFIER au cas o + //return compute_gram_schmidt_basis(ts, m_k); + return ts; // CJTODO: this is only for a sphere in R^3 @@ -1795,7 +1828,7 @@ private: int num_coords = min(ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS - Vectors::const_iterator it_n = m_normals.begin(); + OS_container::const_iterator it_os = m_orth_spaces.begin(); #endif typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -1813,12 +1846,12 @@ private: #ifdef CGAL_TC_EXPORT_NORMALS for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double(coord(*it_n, i)); + os << " " << CGAL::to_double(coord(*it_os->begin(), i)); #endif os << std::endl; } #ifdef CGAL_TC_EXPORT_NORMALS - ++it_n; + ++it_os; #endif } @@ -2219,7 +2252,7 @@ private: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - if (tr.current_dimension() < m_intrinsic_dimension) + if (&tr == NULL || tr.current_dimension() < m_intrinsic_dimension) continue; // Color for this star @@ -2502,15 +2535,15 @@ private: Points_ds m_points_ds; TS_container m_tangent_spaces; +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + OS_container m_orth_spaces; +#endif Tr_container m_triangulations; // Contains the triangulations // and their center vertex Stars_container m_stars; #ifdef CGAL_LINKED_WITH_TBB //std::vector m_tr_mutexes; #endif -#ifdef CGAL_TC_EXPORT_NORMALS - Vectors m_normals; -#endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Points m_points_for_tse; From d40325bae4910607a2374c92c6a1b1cbea824188 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 13 Apr 2015 16:45:46 +0200 Subject: [PATCH 243/487] Added the ability to compute the orthogonal space basis --- .../include/CGAL/Tangential_complex.h | 119 ++++++++++++------ .../CGAL/Tangential_complex/utilities.h | 8 +- 2 files changed, 83 insertions(+), 44 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 42e1ea34b27..8d63b68f583 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -124,6 +124,7 @@ class Tangential_complex typedef typename Tr_traits::Vector_d Tr_vector; typedef std::vector Tangent_space_basis; + typedef std::vector Orthogonal_space_basis; typedef std::vector Points; typedef std::vector Weights; @@ -180,20 +181,21 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; - typedef typename std::vector TS_container; - typedef typename std::vector Tr_container; - typedef typename std::vector Vectors; + typedef typename std::vector TS_container; + typedef typename std::vector OS_container; + typedef typename std::vector Tr_container; + typedef typename std::vector Vectors; // An Incident_simplex is the list of the verter indices // except the center vertex - typedef std::set Incident_simplex; - typedef std::vector Star; - typedef std::vector Stars_container; + typedef std::set Incident_simplex; + typedef std::vector Star; + typedef std::vector Stars_container; #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - //typedef tbb::queuing_mutex Tr_mutex; + //typedef tbb::queuing_mutex Tr_mutex; #endif // For transform_iterator @@ -201,6 +203,11 @@ class Tangential_complex { return vh->point(); } + template + static const P &vertex_handle_to_point(VH vh) + { + return vh->point(); + } public: @@ -261,6 +268,9 @@ public: //m_tr_mutexes.resize(m_points.size()); #endif m_tangent_spaces.resize(m_points.size()); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_orth_spaces.resize(m_points.size()); +#endif #ifdef CGAL_TC_PERTURB_WEIGHT m_weights.resize(m_points.size(), FT(0)); #endif @@ -275,10 +285,6 @@ public: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE m_perturb_tangent_space.resize(m_points.size(), false); #endif -#ifdef CGAL_TC_EXPORT_NORMALS - m_normals.resize(m_points.size(), - m_k.construct_vector_d_object()(m_ambiant_dim)); -#endif #ifdef CGAL_LINKED_WITH_TBB // Parallel @@ -976,8 +982,9 @@ private: // Estimate the tangent space if (!tangent_spaces_are_already_computed) { -#ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i]); #else m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif @@ -985,10 +992,11 @@ private: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { -#ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt,&m_normals[i],true); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt, true); + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); #endif m_perturb_tangent_space[i] = false; } @@ -1151,14 +1159,14 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } - Tangent_space_basis compute_tangent_space(const Point &p -#ifdef CGAL_TC_EXPORT_NORMALS - , Vector *p_normal -#endif + Tangent_space_basis compute_tangent_space( + const Point &p + , bool normalize_basis = true + , Orthogonal_space_basis *p_orth_space_basis = NULL #ifdef CGAL_TC_PERTURB_TANGENT_SPACE - , bool perturb = false + , bool perturb = false #endif - ) const + ) const { //******************************* PCA ************************************* @@ -1216,17 +1224,48 @@ private: i >= m_ambiant_dim - m_intrinsic_dimension ; --i) { - ts.push_back(constr_vec( - m_ambiant_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim)); + if (normalize_basis) + { + ts.push_back(normalize_vector( + constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim), + m_k)); + } + else + { + ts.push_back(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim)); + } + } + + if (p_orth_space_basis) + { + for (int i = m_ambiant_dim - m_intrinsic_dimension - 1 ; + i >= 0 ; + --i) + { + if (normalize_basis) + { + p_orth_space_basis->push_back(normalize_vector( + constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim), + m_k)); + } + else + { + p_orth_space_basis->push_back(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim)); + } + } } -#ifdef CGAL_TC_EXPORT_NORMALS - *p_normal = constr_vec( - m_ambiant_dim, - eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data(), - eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data() + m_ambiant_dim); -#endif //************************************************************************* @@ -1234,7 +1273,7 @@ private: //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; - return compute_gram_schmidt_basis(ts, m_k); + return ts; // CJTODO: this is only for a sphere in R^3 @@ -1795,7 +1834,7 @@ private: int num_coords = min(ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS - Vectors::const_iterator it_n = m_normals.begin(); + OS_container::const_iterator it_os = m_orth_spaces.begin(); #endif typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -1813,12 +1852,12 @@ private: #ifdef CGAL_TC_EXPORT_NORMALS for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double(coord(*it_n, i)); + os << " " << CGAL::to_double(coord(*it_os->begin(), i)); #endif os << std::endl; } #ifdef CGAL_TC_EXPORT_NORMALS - ++it_n; + ++it_os; #endif } @@ -2219,7 +2258,7 @@ private: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - if (tr.current_dimension() < m_intrinsic_dimension) + if (&tr == NULL || tr.current_dimension() < m_intrinsic_dimension) continue; // Color for this star @@ -2502,15 +2541,15 @@ private: Points_ds m_points_ds; TS_container m_tangent_spaces; +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + OS_container m_orth_spaces; +#endif Tr_container m_triangulations; // Contains the triangulations // and their center vertex Stars_container m_stars; #ifdef CGAL_LINKED_WITH_TBB //std::vector m_tr_mutexes; #endif -#ifdef CGAL_TC_EXPORT_NORMALS - Vectors m_normals; -#endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Points m_points_for_tse; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 64e8c4ddfc2..33fcad37772 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -113,16 +113,16 @@ namespace Tangential_complex_ { } };*/ - - + // Modifies v in-place template - std::vector + typename K::Vector_d & normalize_vector( - std::vector &v, + typename K::Vector_d &v, K const& k) { v = k.scaled_vector_d_object()( v, FT(1)/CGAL::sqrt(k.squared_length_d_object()(v))); + return v; } template From 2fb396cadd292aabb38cc4910f2effff4b405e9d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Apr 2015 20:10:27 +0200 Subject: [PATCH 244/487] Function does_voronoi_face_and_alpha_tangent_subspace_intersect --- .../CGAL/Tangential_complex/utilities.h | 153 +++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 33fcad37772..ab8048adcb4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -23,12 +23,30 @@ #include #include +#include +#include +#include + +#include +#include #include #include #include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) +// choose exact integral type for QP solver +#ifdef CGAL_USE_GMP +# include + typedef CGAL::Gmpzf ET; +#else +# include + typedef CGAL::MP_Float ET; +#endif +//#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 + + + namespace CGAL { namespace Tangential_complex_ { @@ -168,7 +186,7 @@ namespace Tangential_complex_ { // Output_iterator::value_type must be std::set > template void combinations(const Elements_container elements, int k, - Output_iterator combinations) + Output_iterator combinations) { std::size_t n = elements.size(); std::vector booleans(n, false); @@ -187,6 +205,139 @@ namespace Tangential_complex_ { } while (std::next_permutation(booleans.begin(), booleans.end())); } + // P: dual face in Delaunay triangulation (p0, p1, pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_alpha_tangent_subspace_intersect( + Point const& center_pt, + Point_range const& P, + Point_range const& Q, + Vector_range const& orthogonal_subspace_basis, + typename K::FT alpha, + K const& k) + { + // Notations: + // Fv: Voronoi k-face + // Fd: dual, (D-k)-face of Delaunay (p0, p1, pn) + + typedef typename K::FT FT; + typedef typename K::Point_d Point; + typedef typename K::Vector_d Vector; + + typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); + typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); + + const int ambient_dim = k.point_dimension_d_object()(center_pt); + + std::size_t card_P = P.size(); + std::size_t card_Q = Q.size(); + std::size_t card_OSB = orthogonal_subspace_basis.size(); + std::size_t num_couples_among_P = card_P*(card_P-1)/2; + std::size_t num_equations = + 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; + + // Linear solver + typedef CGAL::Quadratic_program Linear_program; + typedef CGAL::Quadratic_program_solution LP_solution; + + Linear_program lp(CGAL::SMALLER, false); + int current_row = 0; + + //=========== First set of equations =========== + // For point pi in P + // 2(p0 - pi).x = p0 - pi + Point const& p0 = center_pt; + FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); + for (Point_range::const_iterator it_p = P.begin(), it_p_end = P.end() ; + it_p != it_p_end ; ++it_p) + { + Point const& pi = *it_p; + + for (int k = 0 ; k < ambient_dim ; ++k) + lp.set_a(k, current_row, 2*(p0[k] - pi[k])); + + lp.set_b(current_row, + p0_dot_p0 - scalar_pdct(pt_to_vec(pi), pt_to_vec(pi))); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + // CJTODO: this code might be useful for Option 1 + /*CGAL::Combination_enumerator pi_pj(2, 0, static_cast(card_P)); + for ( ; !pi_pj.finished() ; ++pi_pj) + { + Point const& pi = P[pi_pj[0]]; + Point const& pj = P[pi_pj[1]]; + + for (int k = 0 ; k < ambient_dim ; ++k) + { + FT a = 2*(pi[k] + pj[k]); + lp.set_a(k, current_row , -a); + lp.set_a(k, current_row + 1, a); + } + + FT b = scalar_pdct(pi, pi) - scalar_pdct(pj, pj); + lp.set_b(current_row , -b); + lp.set_b(current_row + 1, b); + + current_row += 2; + }*/ + + //=========== Second set of equations =========== + // For each point qi in Q + // 2(qi - p0).x <= qi - p0 + for (Point_range::const_iterator it_q = Q.begin(), it_q_end = Q.end() ; + it_q != it_q_end ; ++it_q) + { + Point const& qi = *it_q; + + for (int k = 0 ; k < ambient_dim ; ++k) + lp.set_a(k, current_row, 2*(qi[k] - p0[k])); + + lp.set_b(current_row, + scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)) - p0_dot_p0); + + ++current_row; + } + + //=========== Third set of equations =========== + // For each vector of OSB + // bi.x <= bi.p + alpha + // -bi.x <= -bi.p + alpha + for (Vector_range::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; + it_osb != it_osb_end ; ++it_osb) + { + Vector const& bi = *it_osb; + + for (int k = 0 ; k < ambient_dim ; ++k) + { + lp.set_a(k, current_row , bi[k]); + lp.set_a(k, current_row + 1, -bi[k]); + } + + FT bi_dot_p = scalar_pdct(bi, pt_to_vec(center_pt)); + lp.set_b(current_row , bi_dot_p + alpha); + lp.set_b(current_row + 1, -bi_dot_p + alpha); + + current_row += 2; + } + + //=========== Other LP parameters =========== + lp.set_c(0, 1); // Minimize x[0] + + //=========== Solve ========================= + LP_solution solution = CGAL::solve_linear_program(lp, ET()); + if (solution.solves_linear_program(lp)) + std::cout << solution; + else + std::cout << "ERROR\n"; + + return solution.solves_linear_program(lp); + } + } // namespace Tangential_complex_ } //namespace CGAL From bddbd463f0cea91c432328bff92214934e3f9305 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Apr 2015 15:59:55 +0200 Subject: [PATCH 245/487] Use indexed point ranges in does_blabla_intersect --- .../CGAL/Tangential_complex/utilities.h | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index ab8048adcb4..173b161d5b0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -36,13 +36,9 @@ // or tbb::atomic (works for doubles, but not officially) // choose exact integral type for QP solver -#ifdef CGAL_USE_GMP -# include - typedef CGAL::Gmpzf ET; -#else -# include - typedef CGAL::MP_Float ET; -#endif +// (Gmpzf is not thread-safe) +#include +typedef CGAL::MP_Float ET; //#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 @@ -207,11 +203,13 @@ namespace Tangential_complex_ { // P: dual face in Delaunay triangulation (p0, p1, pn) // Q: vertices which are common neighbors of all vertices of P - template + template bool does_voronoi_face_and_alpha_tangent_subspace_intersect( - Point const& center_pt, - Point_range const& P, - Point_range const& Q, + Point_range const& all_points, + std::size_t center_pt_index, + Indexed_point_range const& P, + Indexed_point_range_2 const& Q, Vector_range const& orthogonal_subspace_basis, typename K::FT alpha, K const& k) @@ -227,6 +225,7 @@ namespace Tangential_complex_ { typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); + Point const& center_pt = all_points[center_pt_index]; const int ambient_dim = k.point_dimension_d_object()(center_pt); std::size_t card_P = P.size(); @@ -248,10 +247,11 @@ namespace Tangential_complex_ { // 2(p0 - pi).x = p0 - pi Point const& p0 = center_pt; FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); - for (Point_range::const_iterator it_p = P.begin(), it_p_end = P.end() ; + for (Indexed_point_range::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { - Point const& pi = *it_p; + Point const& pi = all_points[*it_p]; for (int k = 0 ; k < ambient_dim ; ++k) lp.set_a(k, current_row, 2*(p0[k] - pi[k])); @@ -287,10 +287,11 @@ namespace Tangential_complex_ { //=========== Second set of equations =========== // For each point qi in Q // 2(qi - p0).x <= qi - p0 - for (Point_range::const_iterator it_q = Q.begin(), it_q_end = Q.end() ; + for (Indexed_point_range_2::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; it_q != it_q_end ; ++it_q) { - Point const& qi = *it_q; + Point const& qi = all_points[*it_q]; for (int k = 0 ; k < ambient_dim ; ++k) lp.set_a(k, current_row, 2*(qi[k] - p0[k])); @@ -330,12 +331,9 @@ namespace Tangential_complex_ { //=========== Solve ========================= LP_solution solution = CGAL::solve_linear_program(lp, ET()); - if (solution.solves_linear_program(lp)) - std::cout << solution; - else - std::cout << "ERROR\n"; + bool ret = (solution.status() == CGAL::QP_OPTIMAL); - return solution.solves_linear_program(lp); + return ret; } } // namespace Tangential_complex_ From 609d71ac232b29cd9405f37b7f723473469af2a9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Apr 2015 16:01:50 +0200 Subject: [PATCH 246/487] Added a test file for utilities.h --- .../test/Tangential_complex/CMakeLists.txt | 2 + .../Tangential_complex/test_utilities.cpp | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 Tangential_complex/test/Tangential_complex/test_utilities.cpp diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt index c1b10d3b85c..230af037117 100644 --- a/Tangential_complex/test/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -67,6 +67,8 @@ if ( CGAL_FOUND ) ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES) create_single_source_cgal_program( ${SOURCE_FILES} ) + create_single_source_cgal_program( "test_utilities.cpp" ) + else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") endif() diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.cpp b/Tangential_complex/test/Tangential_complex/test_utilities.cpp new file mode 100644 index 00000000000..f902cca8f08 --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/test_utilities.cpp @@ -0,0 +1,57 @@ + +// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB +// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/) +#ifdef _DEBUG +# define TBB_USE_THREADING_TOOL +#endif + +#include +#include + +#include + +using namespace CGAL::Tangential_complex_; + +void test_does_voronoi_face_and_alpha_tangent_subspace_intersect() +{ + typedef CGAL::Epick_d > K; + typedef K::Point_d Pt; + typedef K::Vector_d Vec; + std::vector P; + std::vector Q; + std::vector osb; + + K k; + + std::vector points; + points.push_back(Pt(0.02, -0.03)); + points.push_back(Pt(0.005, 2.3)); + points.push_back(Pt(4.5, 1.12)); + points.push_back(Pt(-3.5, 1.02)); + + P.push_back(0); + P.push_back(1); + + Q.push_back(2); + Q.push_back(3); + + osb.push_back(Vec(0.01, 0.995)); + + assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + points, 0, P, Q, osb, 0.0, k) == false); + + assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + points, 0, P, Q, osb, 0.5, k) == false); + + assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + points, 0, P, Q, osb, 1.0, k) == false); + + assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + points, 0, P, Q, osb, 1.5, k) == true); +} + +int main() +{ + test_does_voronoi_face_and_alpha_tangent_subspace_intersect(); + return 0; +} From 1dff5b1d819656033181310bc397b5592b3d484e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Apr 2015 16:03:44 +0200 Subject: [PATCH 247/487] First implementation of alpha-TC + typos + bug fix in export_to_off --- .../include/CGAL/Tangential_complex.h | 453 ++++++++++++++++-- 1 file changed, 408 insertions(+), 45 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8d63b68f583..6e3d099bf67 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -67,6 +67,10 @@ #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) +#define CGAL_ALPHA_TC +const double ALPHA = 0.3; +tbb::atomic ttt_star; // CJTODO TEMP +tbb::atomic ttt_intersect; namespace CGAL { @@ -186,18 +190,12 @@ class Tangential_complex typedef typename std::vector Tr_container; typedef typename std::vector Vectors; - // An Incident_simplex is the list of the verter indices + // An Incident_simplex is the list of the vertex indices // except the center vertex typedef std::set Incident_simplex; typedef std::vector Star; typedef std::vector Stars_container; -#ifdef CGAL_LINKED_WITH_TBB - // CJTODO: test other mutexes - // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - //typedef tbb::queuing_mutex Tr_mutex; -#endif - // For transform_iterator static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) { @@ -226,7 +224,7 @@ public: m_intrinsic_dimension(intrinsic_dimension), m_half_sparsity(0.5*sparsity), m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), - m_ambiant_dim(k.point_dimension_d_object()(*first)), + m_ambient_dim(k.point_dimension_d_object()(*first)), m_points(first, last) # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) @@ -257,6 +255,8 @@ public: { #ifdef CGAL_TC_PROFILING Wall_clock_timer t; + ttt_intersect = 0; + ttt_star = 0; #endif // We need to do that because we don't want the container to copy the @@ -276,7 +276,7 @@ public: #endif #ifdef CGAL_TC_PERTURB_POSITION m_translations.resize(m_points.size(), - m_k.construct_vector_d_object()(m_ambiant_dim)); + m_k.construct_vector_d_object()(m_ambient_dim)); # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) delete [] m_p_perturb_mutexes; m_p_perturb_mutexes = new Mutex_for_perturb[m_points.size()]; @@ -299,12 +299,18 @@ public: #endif // CGAL_LINKED_WITH_TBB { for (std::size_t i = 0 ; i < m_points.size() ; ++i) +#ifdef CGAL_ALPHA_TC + compute_alpha_tangent_triangulation(i, ALPHA); +#else compute_tangent_triangulation(i); +#endif } #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex computed in " << t.elapsed() << " seconds." << std::endl; + std::cerr << "Intersect: " << ((double)ttt_intersect)/1000000 << " s\n" + << "Star: " << ((double)ttt_star)/1000000 << " s\n"; #endif } @@ -314,7 +320,7 @@ public: typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - std::vector sum_eigen_values(m_ambiant_dim, FT(0)); + std::vector sum_eigen_values(m_ambient_dim, FT(0)); Points::const_iterator it_p = m_points.begin(); Points::const_iterator it_p_end = m_points.end(); @@ -329,13 +335,13 @@ public: //******************************* PCA ************************************* // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambient_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { - for (int i = 0 ; i < m_ambiant_dim ; ++i) + for (int i = 0 ; i < m_ambient_dim ; ++i) mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); @@ -345,7 +351,7 @@ public: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = 0 ; i < m_ambiant_dim ; ++i) + for (int i = 0 ; i < m_ambient_dim ; ++i) sum_eigen_values[i] += eig.eigenvalues()[i]; //************************************************************************* @@ -381,8 +387,13 @@ public: { for (std::size_t i = 0 ; i < m_points.size() ; ++i) { +#ifdef CGAL_ALPHA_TC + compute_alpha_tangent_triangulation(i, ALPHA, + true); // tangent_spaces_are_already_computed +#else compute_tangent_triangulation(i, true); // tangent_spaces_are_already_computed +#endif } } @@ -692,8 +703,7 @@ public: if (m_points.empty()) return os; - const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); - if (ambient_dim < 2) + if (m_ambient_dim < 2) { std::cerr << "Error: export_to_off => ambient dimension should be >= 2." << std::endl; @@ -701,7 +711,7 @@ public: << std::endl; return os; } - if (ambient_dim > 3) + if (m_ambient_dim > 3) { std::cerr << "Warning: export_to_off => ambient dimension should be " "<= 3. Only the first 3 coordinates will be exported." @@ -758,7 +768,6 @@ public: if (m_points.empty()) return true; - const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); typedef Regular_triangulation_euclidean_traits RT_Traits; typedef Regular_triangulation< RT_Traits, @@ -774,7 +783,7 @@ public: // Then save its simplices into "amb_dt_simplices" //------------------------------------------------------------------------- - RT ambient_dt(ambient_dim); + RT ambient_dt(m_ambient_dim); for (std::size_t i=0; i combi( - dim + 1, 0, ambient_dim + 1); + dim + 1, 0, m_ambient_dim + 1); for ( ; !combi.finished() ; ++combi) { @@ -864,7 +873,7 @@ public: std::set diff; if (!incorrect_simplices) incorrect_simplices = &diff; - set_difference(p_simplices->begin(), p_simplices->end(), + std::set_difference(p_simplices->begin(), p_simplices->end(), amb_dt_simplices.begin(), amb_dt_simplices.end(), std::inserter(*incorrect_simplices, incorrect_simplices->begin()) ); @@ -946,8 +955,13 @@ private: { for( size_t i = r.begin() ; i != r.end() ; ++i) { +#ifdef CGAL_ALPHA_TC + m_tc.compute_alpha_tangent_triangulation( + i, ALPHA, m_tangent_spaces_are_already_computed); +#else m_tc.compute_tangent_triangulation( i, m_tangent_spaces_are_already_computed); +#endif } } }; @@ -1159,6 +1173,347 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } + + void compute_alpha_tangent_triangulation( + std::size_t i, FT alpha, bool tangent_spaces_are_already_computed = false, + bool verbose = false) + { + if (verbose) + std::cerr << "** Computing alpha tangent tri #" + << i << " **" << std::endl; + + typedef Regular_triangulation_euclidean_traits Amb_RT_Traits; + typedef Regular_triangulation< + Amb_RT_Traits, + Triangulation_data_structure< + typename Amb_RT_Traits::Dimension, + Triangulation_vertex + > > Amb_RT; + typedef typename Amb_RT::Vertex_handle Amb_RT_VH; + typedef typename Amb_RT::Full_cell_handle Amb_RT_FCH; + //typedef typename Amb_RT::Finite_full_cell_const_iterator Amb_FFC_it; + + typename Kernel::Point_drop_weight_d k_drop_w = + m_k.point_drop_weight_d_object(); + typename Kernel::Squared_distance_d k_sqdist = + m_k.squared_distance_d_object(); + typename Kernel::Point_weight_d k_point_weight = + m_k.point_weight_d_object(); + typename Kernel::Power_center_d k_power_center = + m_k.power_center_d_object(); + + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions + const Point ¢er_pt = m_points[i]; + + // Estimate the tangent space + if (!tangent_spaces_are_already_computed) + { +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i]); +#else + m_tangent_spaces[i] = compute_tangent_space(center_pt); +#endif + } +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + else if (m_perturb_tangent_space[i]) + { +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); +#else + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); +#endif + m_perturb_tangent_space[i] = false; + } +#endif + + //*************************************************** + // Build a minimal triangulation in the tangent space + // (we only need the star of p in the AMBIENT triangulation) + //*************************************************** + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_star; +#endif + + Amb_RT local_amb_tr(m_ambient_dim); + + // Insert p + Weighted_point wp = m_k.construct_weighted_point_d_object()( + center_pt, +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[i] +#else + 0 +#endif + ); + Amb_RT_VH center_vertex = local_amb_tr.insert(wp); + center_vertex->data() = i; + if (verbose) + std::cerr << "* Inserted point #" << i << std::endl; + + INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); + + // While building the local triangulation, we keep the radius + // of the sphere "star sphere" centered at "center_vertex" + // and which contains all the + // circumspheres of the star of "center_vertex" + boost::optional squared_star_sphere_radius_plus_margin; + + // Insert points until we find a point which is outside "star shere" + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { + std::size_t neighbor_point_idx = nn_it->first; + + // ith point = p, which is already inserted + if (neighbor_point_idx != i) + { + // No need to lock the Mutex_for_perturb here since this will not be + // called while other threads are perturbing the positions + Weighted_point neighbor_wp = + compute_perturbed_weighted_point(neighbor_point_idx); + + // "4*m_sq_half_sparsity" because both points can be perturbed + if (squared_star_sphere_radius_plus_margin + && k_sqdist(center_pt, k_drop_w(neighbor_wp)) + > *squared_star_sphere_radius_plus_margin) + break; + + Amb_RT_VH vh = local_amb_tr.insert_if_in_star(neighbor_wp, center_vertex); + //Amb_RT_VH vh = local_amb_tr.insert(neighbor_wp); + if (vh != Amb_RT_VH()) + { + if (verbose) + std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; + + vh->data() = neighbor_point_idx; + + // Let's recompute squared_star_sphere_radius_plus_margin + if (local_amb_tr.current_dimension() == m_ambient_dim) + { + squared_star_sphere_radius_plus_margin = boost::none; + // Get the incident cells and look for the biggest circumsphere + std::vector incident_cells; + local_amb_tr.incident_full_cells( + center_vertex, + std::back_inserter(incident_cells)); + for (typename std::vector::iterator cit = + incident_cells.begin(); cit != incident_cells.end(); ++cit) + { + Amb_RT_FCH cell = *cit; + if (local_amb_tr.is_infinite(cell)) + { + squared_star_sphere_radius_plus_margin = boost::none; + break; + } + else + { + Tr_point c = k_power_center( + boost::make_transform_iterator( + cell->vertices_begin(), + vertex_handle_to_point), + boost::make_transform_iterator( + cell->vertices_end(), + vertex_handle_to_point)); + + FT sq_power_sphere_diam = 4*k_point_weight(c); + + if (!squared_star_sphere_radius_plus_margin + || sq_power_sphere_diam > + *squared_star_sphere_radius_plus_margin) + { + squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; + } + } + } + + // Let's add the margin, now + // The value depends on whether we perturb weight or position + if (squared_star_sphere_radius_plus_margin) + { +#ifdef CGAL_TC_PERTURB_WEIGHT + squared_star_sphere_radius_plus_margin = + *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; +#else + squared_star_sphere_radius_plus_margin = CGAL::square( + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + + 2*m_half_sparsity); +#endif + } + } + } + } + } + +#ifdef CGAL_TC_PROFILING + ttt_star += 1000000*t_star.elapsed(); +#endif + + //*************************************************** + // Parse the faces of the star and add the ones that are in the + // restriction to alpha-Tp + // Update the associated star (in m_stars) + //*************************************************** + Star &star = m_stars[i]; + star.clear(); + int cur_dim_plus_1 = m_ambient_dim + 1; + + std::vector incident_cells; + local_amb_tr.incident_full_cells( + center_vertex, std::back_inserter(incident_cells)); + + typedef std::set DT_face; // DT face without center vertex (i) + typedef std::set Neighbor_vertices; + typedef std::map DT_faces_and_neighbors; + + // Maps that associate a k-face and the list of its neighbor points + // (i.e. there are k+1-cofaces that contain these points) + // N.B.: each k-face contains 'i', so 'i' is not stored in the faces + // faces_and_neighbors[0] => dim 1, faces_and_neighbors[1] => dim 2 + std::vector faces_and_neighbors; + faces_and_neighbors.resize(m_ambient_dim); + + // Fill faces_and_neighbors + // Let's first take care of the D-faces + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + DT_face face; + // CJTODO: use (*it_c)->vertices_begin(), etc. + for (int j = 0 ; j < cur_dim_plus_1 ; ++j) + { + std::size_t index = (*it_c)->vertex(j)->data(); + if (index == std::numeric_limits::max()) + goto next_face; + if (index != i) + face.insert(index); + } + faces_and_neighbors[m_ambient_dim-1][face] = Neighbor_vertices(); +next_face: + ; + } + // Then the D-k-faces... + int current_dim = m_ambient_dim - 1; + while (current_dim > 0) + { + // Let's fill faces_and_neighbors[current_dim-1] + // (stores the current_dim-faces) + DT_faces_and_neighbors& cur_faces_and_nghb = + faces_and_neighbors[current_dim-1]; + + typedef DT_faces_and_neighbors::const_iterator FaN_it; + // Parse k+1-faces + for (FaN_it it_k_p1_face = faces_and_neighbors[current_dim].begin(), + it_k_p1_face_end = faces_and_neighbors[current_dim].end() ; + it_k_p1_face != it_k_p1_face_end ; ++it_k_p1_face) + { + DT_face const& k_p1_face = it_k_p1_face->first; + + // Add each k faces to cur_faces_and_nghb + std::size_t n = current_dim + 1; // Not +2 since 'i' is not stored + std::vector booleans(n, false); + std::fill(booleans.begin() + 1, booleans.end(), true); + do + { + DT_face k_face; + std::size_t remaining_vertex; + DT_face::const_iterator it_v = k_p1_face.begin(); + for (std::size_t i = 0 ; i < n ; ++i, ++it_v) + { + if (booleans[i]) + k_face.insert(*it_v); + else + remaining_vertex = *it_v; + } + + cur_faces_and_nghb[k_face].insert(remaining_vertex); + + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + --current_dim; + } + + // For each face V of Voronoi_cell(P[i]) - dim 0 to dim D-1 + // I.e. For each DT face F of the star - dim D to dim 1 + current_dim = m_ambient_dim; + while (current_dim > 0) + { + // Remember: faces_and_neighbors[current_dim-1] stores + // the current_dim-faces + DT_faces_and_neighbors const& cur_faces_and_nghb = + faces_and_neighbors[current_dim-1]; + + for (DT_faces_and_neighbors::const_iterator + it_f = cur_faces_and_nghb.begin(), + it_f_end = cur_faces_and_nghb.end() ; + it_f != it_f_end ; ++it_f) + { + Neighbor_vertices const& curr_neighbors = it_f->second; + + DT_face const& current_DT_face = it_f->first; + CGAL_assertion(static_cast(current_DT_face.size()) + == current_dim); + + // P: list of current_DT_face points (including 'i') + std::vector P( + current_DT_face.begin(), current_DT_face.end()); + P.push_back(i); + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_inters; +#endif + bool does_intersect = + does_voronoi_face_and_alpha_tangent_subspace_intersect( + m_points, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); +#ifdef CGAL_TC_PROFILING + ttt_intersect += 1000000*t_inters.elapsed(); +#endif + if (does_intersect) + { + star.push_back(current_DT_face); + + // Clear all subfaces of current_DT_face from the maps + for (int dim = current_dim - 1 ; dim > 0 ; --dim) + { + std::size_t n = current_DT_face.size(); + std::vector booleans(n, false); + std::fill(booleans.begin() + n - dim, booleans.end(), true); + do + { + DT_face dim_face; + DT_face::const_iterator it_v = current_DT_face.begin(); + for (std::size_t i = 0 ; i < n ; ++i, ++it_v) + { + if (booleans[i]) + dim_face.insert(*it_v); + } + + faces_and_neighbors[dim-1].erase(dim_face); + + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + } + } + + --current_dim; + } + + // CJTODO DEBUG + //std::cerr << "\nChecking topology and geometry..." + // << (local_amb_tr.is_valid(true) ? "OK.\n" : "Error.\n"); + // DEBUG: output the local mesh into an OFF file + //std::stringstream sstr; + //sstr << "data/local_tri_" << i << ".off"; + //std::ofstream off_stream_tr(sstr.str()); + //CGAL::export_triangulation_to_off(off_stream_tr, local_amb_tr); + } + Tangent_space_basis compute_tangent_space( const Point &p , bool normalize_basis = true @@ -1196,13 +1551,13 @@ private: #endif // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambient_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { - for (int i = 0 ; i < m_ambiant_dim ; ++i) + for (int i = 0 ; i < m_ambient_dim ; ++i) { //const Point p = transl( // m_points[nn_it->first], m_translations[nn_it->first]); @@ -1220,31 +1575,31 @@ private: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = m_ambiant_dim - 1 ; - i >= m_ambiant_dim - m_intrinsic_dimension ; + for (int i = m_ambient_dim - 1 ; + i >= m_ambient_dim - m_intrinsic_dimension ; --i) { if (normalize_basis) { ts.push_back(normalize_vector( constr_vec( - m_ambiant_dim, + m_ambient_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim), + eig.eigenvectors().col(i).data() + m_ambient_dim), m_k)); } else { ts.push_back(constr_vec( - m_ambiant_dim, + m_ambient_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim)); + eig.eigenvectors().col(i).data() + m_ambient_dim)); } } if (p_orth_space_basis) { - for (int i = m_ambiant_dim - m_intrinsic_dimension - 1 ; + for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; i >= 0 ; --i) { @@ -1252,17 +1607,17 @@ private: { p_orth_space_basis->push_back(normalize_vector( constr_vec( - m_ambiant_dim, + m_ambient_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim), + eig.eigenvectors().col(i).data() + m_ambient_dim), m_k)); } else { p_orth_space_basis->push_back(constr_vec( - m_ambiant_dim, + m_ambient_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim)); + eig.eigenvectors().col(i).data() + m_ambient_dim)); } } } @@ -1544,7 +1899,7 @@ private: typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(m_ambiant_dim, 1); + tr_point_on_sphere_generator(m_ambient_dim, 1); // Parallel # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) Vector transl = k_scaled_vec(k_pt_to_vec( @@ -1576,7 +1931,7 @@ private: Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( *tr_point_on_sphere_generator++, 0); - Translation_for_perturb global_transl = k_constr_vec(m_ambiant_dim); + Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { @@ -1826,13 +2181,12 @@ private: // to be able to export each segment as a flat triangle with 3 different // indices (otherwise, Meshlab detects degenerated simplices) const int N = (m_intrinsic_dimension == 1 ? 2 : 1); - const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - int num_coords = min(ambient_dim, 3); + int num_coords = min(m_ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS OS_container::const_iterator it_os = m_orth_spaces.begin(); #endif @@ -2296,15 +2650,20 @@ private: c) != p_additional_simpl_to_color->end()); } - // If only 2 vertices, add a third one (each vertex is duplicated in + + // If m_intrinsic_dimension = 1, each point is output two times, + // so we need to multiply each index by 2 + // And if only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) - if (num_vertices == 2) + if (m_intrinsic_dimension == 1) { std::set tmp_c; std::set::iterator it = c.begin(); for ( ; it != c.end() ; ++it) tmp_c.insert(*it * 2); - tmp_c.insert(*c.rbegin() + 1); + if (num_vertices == 2) + tmp_c.insert(*tmp_c.rbegin() + 1); + c = tmp_c; } @@ -2440,15 +2799,19 @@ private: if (num_vertices < m_intrinsic_dimension + 1) continue; - // If only 2 vertices, add a third one (each vertex is duplicated in + // If m_intrinsic_dimension = 1, each point is output two times, + // so we need to multiply each index by 2 + // And if only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) - if (num_vertices == 2) + if (m_intrinsic_dimension == 1) { std::set tmp_c; std::set::iterator it = c.begin(); for ( ; it != c.end() ; ++it) tmp_c.insert(*it * 2); - tmp_c.insert(*c.rbegin() + 1); + if (num_vertices == 2) + tmp_c.insert(*tmp_c.rbegin() + 1); + c = tmp_c; } @@ -2523,7 +2886,7 @@ private: const int m_intrinsic_dimension; const double m_half_sparsity; const double m_sq_half_sparsity; - const int m_ambiant_dim; + const int m_ambient_dim; Points m_points; #ifdef CGAL_TC_PERTURB_WEIGHT From 26d07750f868277d4df6a2c99456e3adb6dccdba Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 17 Apr 2015 17:10:00 +0200 Subject: [PATCH 248/487] Temporary code to test the alpha-TC --- .../Tangential_complex/benchmark_tc.cpp | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 308d3e950ad..4803abccfae 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -183,6 +183,37 @@ void make_tc(std::vector &points, int intrinsic_dim, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); + // CJTODO TEMP =========================== + { + TC::Simplicial_complex complex; + int max_dim = tc.export_TC(complex, false); + complex.display_stats(); + + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim + << "_in_R" << ambient_dim << "_ALPHA_COMPLEX.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(complex, off_stream); + + // Collapse + complex.collapse(max_dim); + { + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim + << "_in_R" << ambient_dim << "_AFTER_COLLAPSE.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(complex, off_stream); + } + std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces; + bool pure_manifold = complex.is_pure_manifold( + intrinsic_dim, false, 1, + &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); + complex.display_stats(); + } + + return; + // CJTODO TEMP =========================== + //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); double export_before_time = -1.; @@ -198,6 +229,7 @@ void make_tc(std::vector &points, int intrinsic_dim, } + t.reset(); unsigned int num_fix_steps; std::size_t initial_num_inconsistent_local_tr; @@ -254,7 +286,7 @@ void make_tc(std::vector &points, int intrinsic_dim, } // Collapse - complex.collapse(max_dim); + //complex.collapse(max_dim); double export_after_collapse_time = -1.; if (intrinsic_dim <= 3) @@ -271,6 +303,7 @@ void make_tc(std::vector &points, int intrinsic_dim, bool pure_manifold = complex.is_pure_manifold( intrinsic_dim, false, 0, &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); + complex.display_stats(); std::cerr << std::endl From 509bff1152858632e10e283825e59a4fd923b93b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 12:54:22 +0200 Subject: [PATCH 249/487] Add is_pure_pseudomanifold__do_not_check_if_stars_are_connected + minor changes --- .../Tangential_complex/Simplicial_complex.h | 235 +++++++++++++++++- 1 file changed, 224 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index e386739020f..dac05d35a89 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -26,6 +26,13 @@ #include #include +#include + +// For is_pure_pseudomanifold +#include +#include +#include +#include namespace CGAL { namespace Tangential_complex_ { @@ -46,8 +53,19 @@ public: return m_complex; } - void collapse(int max_simplex_dim) + void clear() { + m_complex.clear(); + } + + // When a simplex S has only one co-face C, we can remove S and C + // without changing the topology + void collapse(int max_simplex_dim, bool quiet = false) + { +#ifdef CGAL_TC_VERBOSE + if (!quiet) + std::cerr << "Collapsing... "; +#endif // We note k = max_simplex_dim - 1 int k = max_simplex_dim - 1; @@ -121,7 +139,12 @@ public: // Collapse the lower dimension simplices if (k > 0) - collapse(max_simplex_dim - 1); + collapse(max_simplex_dim - 1, true); + +#ifdef CGAL_TC_VERBOSE + if (!quiet) + std::cerr << "done." << std::endl; +#endif } void display_stats() const @@ -137,9 +160,6 @@ public: { // Number of simplex for each dimension std::map simplex_stats; - - typedef std::set Simplex; - typedef std::set Complex; for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; @@ -161,16 +181,18 @@ public: } // verbose_level = 0, 1 or 2 - bool is_pure_manifold(int simplex_dim, - bool exit_at_the_first_problem = false, - int verbose_level = 0, - std::size_t *p_num_wrong_dim_simplices = NULL, - std::size_t *p_num_wrong_number_of_cofaces = NULL) + bool is_pure_pseudomanifold__do_not_check_if_stars_are_connected( + int simplex_dim, + bool exit_at_the_first_problem = false, + int verbose_level = 0, + std::size_t *p_num_wrong_dim_simplices = NULL, + std::size_t *p_num_wrong_number_of_cofaces = NULL) { typedef std::set K_1_face; typedef std::map Cofaces_map; - std::size_t num_wrong_dim_simplices = 0, num_wrong_number_of_cofaces = 0; + std::size_t num_wrong_dim_simplices = 0; + std::size_t num_wrong_number_of_cofaces = 0; // Counts the number of cofaces of each K_1_face @@ -242,8 +264,199 @@ public: return ret; } + // CJTODO: ADD COMMENTS + bool is_pure_pseudomanifold( + int simplex_dim, + std::size_t num_vertices, + bool exit_at_the_first_problem = false, + int verbose_level = 0, + std::size_t *p_num_wrong_dim_simplices = NULL, + std::size_t *p_num_wrong_number_of_cofaces = NULL, + std::size_t *p_num_unconnected_stars = NULL, + Simplex_range *p_wrong_dim_simplices = NULL, + Simplex_range *p_wrong_number_of_cofaces_simplices = NULL, + Simplex_range *p_unconnected_stars_simplices = NULL) + { + // If simplex_dim == 1, we do not need to check if stars are connected + if (simplex_dim == 1) + { + if (p_num_unconnected_stars) + *p_num_unconnected_stars = 0; + return is_pure_pseudomanifold__do_not_check_if_stars_are_connected( + simplex_dim, + exit_at_the_first_problem, + verbose_level, + p_num_wrong_dim_simplices, + p_num_wrong_number_of_cofaces); + } + // Associates each vertex (= the index in the vector) + // to its star (list of simplices) + typedef std::vector > Stars; + std::size_t num_wrong_dim_simplices = 0; + std::size_t num_wrong_number_of_cofaces = 0; + std::size_t num_unconnected_stars = 0; + + // Fills a Stars data structure + Stars stars; + stars.resize(num_vertices); + for (Complex::const_iterator it_simplex = m_complex.begin(), + it_simplex_end = m_complex.end() ; + it_simplex != it_simplex_end ; + ++it_simplex) + { + if (it_simplex->size() != simplex_dim + 1) + { + if (verbose_level >= 2) + std::cerr << "Found a simplex with dim = " + << it_simplex->size() - 1 << std::endl; + ++num_wrong_dim_simplices; + if (p_wrong_dim_simplices) + p_wrong_dim_simplices->insert(*it_simplex); + } + else + { + for (Simplex::const_iterator it_point_idx = it_simplex->begin() ; + it_point_idx != it_simplex->end() ; + ++it_point_idx) + { + stars[*it_point_idx].push_back(it_simplex); + } + } + } + + // Now, for each star, with have a vector of its d-simplices + // i.e. one index for each d-simplex + // Boost Graph only deals with indexes, so we also need indexes for the + // (d-1)-simplices + std::size_t center_vertex_index = 0; + for (Stars::const_iterator it_star = stars.begin() ; + it_star != stars.end() ; + ++it_star, ++center_vertex_index) + { + typedef std::map > + Dm1_faces_to_adj_D_faces; + Dm1_faces_to_adj_D_faces dm1_faces_to_adj_d_faces; + + for (int i_dsimpl = 0 ; i_dsimpl < it_star->size() ; ++i_dsimpl) + { + Simplex dm1_simpl_of_link = *((*it_star)[i_dsimpl]); + dm1_simpl_of_link.erase(center_vertex_index); + // Copy it to a vector so that we can use operator[] on it + std::vector dm1_simpl_of_link_vec( + dm1_simpl_of_link.begin(), dm1_simpl_of_link.end()); + + CGAL::Combination_enumerator dm2_simplices( + simplex_dim - 1, 0, simplex_dim); + for ( ; !dm2_simplices.finished() ; ++dm2_simplices) + { + Simplex dm2_simpl; + for (int j = 0 ; j < simplex_dim - 1 ; ++j) + dm2_simpl.insert(dm1_simpl_of_link_vec[dm2_simplices[j]]); + dm1_faces_to_adj_d_faces[dm2_simpl].push_back(i_dsimpl); + } + } + + Adj_graph adj_graph; + std::vector d_faces_descriptors; + d_faces_descriptors.resize(it_star->size()); + for (int j = 0 ; j < it_star->size() ; ++j) + d_faces_descriptors[j] = boost::add_vertex(adj_graph); + + Dm1_faces_to_adj_D_faces::const_iterator dm1_to_d_it = + dm1_faces_to_adj_d_faces.begin(); + Dm1_faces_to_adj_D_faces::const_iterator dm1_to_d_it_end = + dm1_faces_to_adj_d_faces.end(); + for (std::size_t i_km1_face = 0 ; + dm1_to_d_it != dm1_to_d_it_end ; + ++dm1_to_d_it, ++i_km1_face) + { + Graph_vertex km1_gv = boost::add_vertex(adj_graph); + + for (std::vector::const_iterator kface_it = + dm1_to_d_it->second.begin() ; + kface_it != dm1_to_d_it->second.end() ; + ++kface_it) + { + boost::add_edge(km1_gv, *kface_it, adj_graph); + } + + if (dm1_to_d_it->second.size() != 2) + { + ++num_wrong_number_of_cofaces; + if (p_wrong_number_of_cofaces_simplices) + { + for (auto idx : dm1_to_d_it->second) + p_wrong_number_of_cofaces_simplices->insert(*((*it_star)[idx])); + } + } + } + + // What is left is to check the connexity + std::vector components(boost::num_vertices(adj_graph)); + bool is_connected = + (boost::connected_components(adj_graph, &components[0]) == 1); + + if (!is_connected) + { + if (verbose_level >= 2) + std::cerr << "Error: star #" << center_vertex_index + << " is not connected" << std::endl; + ++num_unconnected_stars; + if (p_unconnected_stars_simplices) + { + for (std::vector::const_iterator + it_simpl = it_star->begin(), + it_simpl_end = it_star->end(); + it_simpl != it_simpl_end ; + ++it_simpl) + { + p_unconnected_stars_simplices->insert(**it_simpl); + } + } + } + } + + // Each one has been counted several times ("simplex_dim" times) + num_wrong_number_of_cofaces /= simplex_dim; + + bool ret = + num_wrong_dim_simplices == 0 + && num_wrong_number_of_cofaces == 0 + && num_unconnected_stars == 0; + + if (verbose_level >= 1) + { + std::cerr << "is_pure_pseudo_manifold: " + << (ret ? "YES" : "NO") << std::endl; + if (!ret) + { + std::cerr << " * Number of wrong dimension simplices: " + << num_wrong_dim_simplices << std::endl + << " * Number of wrong number of cofaces: " + << num_wrong_number_of_cofaces << std::endl + << " * Number of not-connected stars: " + << num_unconnected_stars << std::endl; + } + } + + if (p_num_wrong_dim_simplices) + *p_num_wrong_dim_simplices = num_wrong_dim_simplices; + if (p_num_wrong_number_of_cofaces) + *p_num_wrong_number_of_cofaces = num_wrong_number_of_cofaces; + if (p_num_unconnected_stars) + *p_num_unconnected_stars = num_unconnected_stars; + + return ret; + } + private: typedef Simplex_range Complex; + + // graph is an adjacency list + typedef boost::adjacency_list Adj_graph; + // map that gives to a certain simplex its node in graph and its dimension + typedef boost::graph_traits::vertex_descriptor Graph_vertex; + typedef boost::graph_traits::edge_descriptor Graph_edge; Complex m_complex; From 7fab99906a6f8d36df2b04a1fe3dc7a5b594611b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 12:57:04 +0200 Subject: [PATCH 250/487] Allow several colors in export_to_off + const correctness --- .../include/CGAL/Tangential_complex.h | 166 ++++++++++++------ 1 file changed, 116 insertions(+), 50 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6e3d099bf67..2f88a7b36cc 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -76,7 +76,8 @@ namespace CGAL { using namespace Tangential_complex_; -enum Fix_inconsistencies_status { TC_FIXED = 0, TIME_LIMIT_REACHED }; +enum Fix_inconsistencies_status { + TC_FIXED = 0, TIME_LIMIT_REACHED, FIX_NOT_PERFORMED }; class Vertex_data { @@ -246,6 +247,15 @@ public: #endif } + int intrinsic_dimension() const + { + return m_intrinsic_dimension; + } + int ambient_dimension() const + { + return m_ambient_dim; + } + std::size_t number_of_vertices() { return m_points.size(); @@ -619,7 +629,7 @@ public: // Return the max dimension of the simplices int export_TC(Simplicial_complex &complex, - bool export_infinite_simplices = false) + bool export_infinite_simplices = false) const { int max_dim = -1; @@ -690,15 +700,22 @@ public: std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, - std::set > const *p_additional_simpl_to_color = NULL) + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL) + const { - return export_to_off(os, false, p_additional_simpl_to_color, &complex); + return export_to_off( + os, false, p_simpl_to_color_in_red, p_simpl_to_color_in_green, + p_simpl_to_color_in_blue, &complex); } std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, - std::set > const *p_additional_simpl_to_color = NULL, - const Simplicial_complex *p_complex = NULL) + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL, + const Simplicial_complex *p_complex = NULL) const { if (m_points.empty()) return os; @@ -735,13 +752,14 @@ public: if (p_complex) { export_simplices_to_off( - *p_complex, output, num_simplices, p_additional_simpl_to_color); + *p_complex, output, num_simplices, p_simpl_to_color_in_red, + p_simpl_to_color_in_green, p_simpl_to_color_in_blue); } else { export_simplices_to_off( - output, num_simplices, color_inconsistencies, - p_additional_simpl_to_color); + output, num_simplices, color_inconsistencies, p_simpl_to_color_in_red, + p_simpl_to_color_in_green, p_simpl_to_color_in_blue); } #ifdef CGAL_TC_EXPORT_NORMALS @@ -1664,7 +1682,7 @@ next_face: */ } - Point compute_perturbed_point(std::size_t pt_idx) + Point compute_perturbed_point(std::size_t pt_idx) const { #ifdef CGAL_TC_PERTURB_POSITION return m_k.translated_point_d_object()( @@ -1809,7 +1827,7 @@ next_face: } // A simplex here is a local tri's full cell handle - bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) + bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) const { std::set c; for (int i = 0 ; i < cur_dim + 1 ; ++i) @@ -1821,7 +1839,7 @@ next_face: } // A simplex here is a list of point indices - bool is_simplex_consistent(std::set const& simplex) + bool is_simplex_consistent(std::set const& simplex) const { int cur_dim_plus_1 = static_cast(simplex.size()); @@ -2169,7 +2187,7 @@ next_face: std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices, - bool use_perturbed_points = false) + bool use_perturbed_points = false) const { if (m_points.empty()) { @@ -2595,7 +2613,10 @@ next_face: std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_simplices, bool color_inconsistencies = false, - std::set > const *p_additional_simpl_to_color = NULL) + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL) + const { // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) @@ -2620,8 +2641,8 @@ next_face: //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; color << 128 << " " << 128 << " " << 128; - // Gather the triangles here, with a bool saying if it's consistent - typedef std::vector, bool> > + // Gather the triangles here, with an int telling its color + typedef std::vector, int> > Star_using_triangles; Star_using_triangles star_using_triangles; @@ -2634,22 +2655,40 @@ next_face: c.insert(idx); std::size_t num_vertices = c.size(); - bool color_simplex = false; + int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue if (color_inconsistencies) { - color_simplex = !is_simplex_consistent(c); - if (color_simplex) - is_star_inconsistent = true; + is_star_inconsistent = !is_simplex_consistent(c); + color_simplex = (is_star_inconsistent ? 0 : -1); } - if (p_additional_simpl_to_color && !color_simplex) + if (color_simplex == -1) { - color_simplex = (std::find( - p_additional_simpl_to_color->begin(), - p_additional_simpl_to_color->end(), - c) != p_additional_simpl_to_color->end()); + if (p_simpl_to_color_in_red && + std::find( + p_simpl_to_color_in_red->begin(), + p_simpl_to_color_in_red->end(), + c) != p_simpl_to_color_in_red->end()) + { + color_simplex = 1; + } + else if (p_simpl_to_color_in_green && + std::find( + p_simpl_to_color_in_green->begin(), + p_simpl_to_color_in_green->end(), + c) != p_simpl_to_color_in_green->end()) + { + color_simplex = 2; + } + else if (p_simpl_to_color_in_blue && + std::find( + p_simpl_to_color_in_blue->begin(), + p_simpl_to_color_in_blue->end(), + c) != p_simpl_to_color_in_blue->end()) + { + color_simplex = 3; + } } - // If m_intrinsic_dimension = 1, each point is output two times, // so we need to multiply each index by 2 @@ -2704,7 +2743,7 @@ next_face: continue; const std::set &c = it_simplex->first; - bool color_simplex = it_simplex->second; + int color_simplex = it_simplex->second; std::stringstream sstr_c; @@ -2716,19 +2755,21 @@ next_face: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != idx && !color_simplex) + if (*c.begin() != idx && color_simplex == -1) continue; os << 3 << " " << sstr_c.str(); - if (color_inconsistencies || p_additional_simpl_to_color) + if (color_inconsistencies || p_simpl_to_color_in_red + || p_simpl_to_color_in_green || p_simpl_to_color_in_blue) { - if (color_simplex) + switch (color_simplex) { - os << " 255 0 0"; - ++num_inconsistent_simplices; - } - else - os << " " << color.str(); + case 0: os << " 255 255 0"; ++num_inconsistent_simplices; break; + case 1: os << " 255 0 0"; break; + case 2: os << " 0 255 0"; break; + case 3: os << " 0 0 255"; break; + default: os << " " << color.str(); break; + } } ++num_simplices; os << std::endl; @@ -2764,7 +2805,10 @@ next_face: std::ostream &export_simplices_to_off( const Simplicial_complex &complex, std::ostream & os, std::size_t &num_simplices, - std::set > const *p_additional_simpl_to_color = NULL) + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL) + const { typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; @@ -2780,15 +2824,32 @@ next_face: for ( ; it_s != it_s_end ; ++it_s) { Simplex c = *it_s; - - bool color_simplex = false; - if (p_additional_simpl_to_color) - { - color_simplex = (std::find( - p_additional_simpl_to_color->begin(), - p_additional_simpl_to_color->end(), - c) != p_additional_simpl_to_color->end()); - } + + int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue + if (p_simpl_to_color_in_red && + std::find( + p_simpl_to_color_in_red->begin(), + p_simpl_to_color_in_red->end(), + c) != p_simpl_to_color_in_red->end()) + { + color_simplex = 1; + } + else if (p_simpl_to_color_in_green && + std::find( + p_simpl_to_color_in_green->begin(), + p_simpl_to_color_in_green->end(), + c) != p_simpl_to_color_in_green->end()) + { + color_simplex = 2; + } + else if (p_simpl_to_color_in_blue && + std::find( + p_simpl_to_color_in_blue->begin(), + p_simpl_to_color_in_blue->end(), + c) != p_simpl_to_color_in_blue->end()) + { + color_simplex = 3; + } // Gather the triangles here typedef std::vector Triangles; @@ -2854,12 +2915,17 @@ next_face: os << *it_point_idx << " "; } - if (p_additional_simpl_to_color) + if (p_simpl_to_color_in_red || p_simpl_to_color_in_green + || p_simpl_to_color_in_blue) { - if (color_simplex) - os << " 255 0 0"; - else - os << " 128 128 128"; + switch (color_simplex) + { + case 0: os << " 255 255 0"; break; + case 1: os << " 255 0 0"; break; + case 2: os << " 0 255 0"; break; + case 3: os << " 0 0 255"; break; + default: os << " 128 128 128"; break; + } } ++num_simplices; From 268cd0994b67a9b73dea065b19f0385fa66c9642 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 12:57:52 +0200 Subject: [PATCH 251/487] Improved benchmark (comments, output...) --- .../Tangential_complex/benchmark_script.txt | 82 ++-- .../Tangential_complex/benchmark_tc.cpp | 379 ++++++++++++------ 2 files changed, 310 insertions(+), 151 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 0aa065fd7a8..a26d5085ada 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -1,42 +1,54 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- -# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY FIX_TIME_LIMIT NUM_ITERATIONS +# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- -#---------------------------------------------------------- Very small cases for Debug mode ------------------------------------------------------------- -#generate_sphere_d 3 - - 20 3 2 0.05 60 1 -#generate_klein_bottle_4D 4 3 - 70 4 2 1.5 60 1 +#---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- +#generate_sphere_d 4 - - 20 3 2 0.05 N N Y 60 1 +#generate_sphere_d 3 - - 70 3 2 0.05 Y Y Y 60 1 +#generate_sphere_d 3 - - 1000 3 2 0.05 Y Y Y 60 1 +#generate_sphere_d 3 - - 70 4 3 0.05 Y Y Y 60 1 +#generate_sphere_d 3 - - 70 5 4 0.05 Y Y Y 60 1 +#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 Y Y Y 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.7 Y Y Y 60 1 +#generate_moment_curve 0 1 - 30 3 1 0.005 Y Y Y 60 1 -#------------------------------------------------------------------ From files --------------------------------------------------------------------------- -data/SO3_50000.txt - - - 0 9 3 0.2 60 1 -data/SO3_10000.txt - - - 0 9 3 0.05 60 1 -#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 3000 1 -#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 3000 1 -#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 3000 1 -data/Cy8.txt - - - 0 24 2 0.1 60 1 -data/Kl.txt - - - 0 5 2 0.05 60 1 -data/S3.txt - - - 0 4 3 0.05 60 1 +#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ +#generate_sphere_d 0.302 - - 70 2 1 0.005 N N Y 60 1 +#generate_sphere_d 0.5 - - 70 2 1 0.005 N N Y 60 1 +generate_klein_bottle_4D 40 15 - 130 4 2 0.2 N N Y 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 Y Y Y 60 1 #Takes forever -#---------------------------------------------------------------------- 3D meshes ------------------------------------------------------------------------ -data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 -data/fandisk.txt - - - 0 3 2 0.01 60 1 -data/fertility.txt - - - 0 3 2 0.4 60 1 -data/bunny.txt - - - 0 3 2 0.5 60 1 -data/blob.txt - - - 0 3 2 0.01 60 1 -data/3holes.txt - - - 0 3 2 0.01 60 1 -data/785_hand_2500v.txt - - - 0 3 2 0.01 60 1 -data/785_hand_50kv.txt - - - 0 3 2 0.01 60 1 -data/bumpy_sphere.txt - - - 0 3 2 0.01 60 1 +#------------------------------------------------------------------ From files -------------------------------------------------------------------------- +#data/SO3_50000.txt - - - 0 9 3 0.2 Y Y Y 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.05 Y Y Y 60 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 Y Y Y 3000 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 Y Y Y 3000 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 Y Y Y 3000 1 +#data/Cy8.txt - - - 0 24 2 0.1 Y Y Y 60 1 +#data/Kl.txt - - - 0 5 2 0.05 Y Y Y 60 1 +#data/S3.txt - - - 0 4 3 0.05 Y Y Y 60 1 -#----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ -#generate_sphere_d 3 - - 4 3 2 0.05 3000 1 -#generate_sphere_d 3 - - 30000 2 1 0.005 3000 1 -#generate_sphere_d 3 - - 30000 3 2 0.005 3000 1 -#generate_sphere_d 3 - - 30000 4 3 0.05 3000 1 -#generate_plane - - - 30000 3 2 0.005 3000 1 -generate_moment_curve 0 1 - 30000 6 1 0.005 60 1 -generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 60 1 -generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 +#---------------------------------------------------------------------- 3D meshes ----------------------------------------------------------------------- +#data/buddha_100kv.txt - - - 0 3 2 0.005 Y Y Y 60 1 +#data/fandisk.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/fertility.txt - - - 0 3 2 0.4 Y Y Y 60 1 +#data/bunny.txt - - - 0 3 2 0.5 Y Y Y 60 1 +#data/blob.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/3holes.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/785_hand_2500v.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/785_hand_50kv.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/bumpy_sphere.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------- -# TC: 5.55 / 1st fix step : 0.2 -#data/fertility.txt - - - 0 3 2 0.1 100 1 \ No newline at end of file +#----------------------------------------------------------- Generated point sets ----------------------------------------------------------------------- +#generate_sphere_d 3 - - 4 3 2 0.05 Y Y Y 3000 1 +#generate_sphere_d 3 - - 30000 2 1 0.005 Y Y Y 3000 1 +#generate_sphere_d 3 - - 30000 3 2 0.005 Y Y Y 3000 1 +#generate_sphere_d 3 - - 30000 4 3 0.05 Y Y Y 3000 1 +#generate_plane - - - 30000 3 2 0.005 Y Y Y 3000 1 +#generate_moment_curve 0 1 - 30000 6 1 0.005 Y Y Y 60 1 +#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 Y Y Y 60 1 +#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 Y Y Y 60 1 + +#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------ +# TC: 5.55 / 1st fix step : 0.2 +#data/fertility.txt - - - 0 3 2 0.1 Y Y Y 100 1 \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 4803abccfae..ae2b8310809 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -91,12 +91,14 @@ protected: subelements.push_back("Final_num_inconsistent_local_tr"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); - subelements.push_back("Fix1_successful"); - subelements.push_back("Fix1_time"); - subelements.push_back("Fix1_steps"); - subelements.push_back("Fix2_pure_manifold"); - subelements.push_back("Fix2_num_wrong_number_of_cofaces"); - subelements.push_back("Fix2_time"); + subelements.push_back("Perturb_successful"); + subelements.push_back("Perturb_time"); + subelements.push_back("Perturb_steps"); + subelements.push_back("Add_higher_dim_simpl_time"); + subelements.push_back("Result_pure_pseudomanifold"); + subelements.push_back("Result_num_wrong_dim_simplices"); + subelements.push_back("Result_num_wrong_number_of_cofaces"); + subelements.push_back("Result_num_unconnected_stars"); subelements.push_back("Info"); return subelements; @@ -125,13 +127,94 @@ protected: XML_exporter::Element_with_map m_current_element; }; -void make_tc(std::vector &points, int intrinsic_dim, - double sparsity = 0., double time_limit_for_fix = 0., +template +bool export_to_off( + TC const& tc, + std::string const& input_name_stripped, + std::string const& suffix, + bool color_inconsistencies = false, + typename TC::Simplicial_complex const* p_complex = NULL, + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL) +{ + if (tc.intrinsic_dimension() <= 3) + { + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" + << tc.intrinsic_dimension() << "_in_R" + << tc.ambient_dimension() << suffix << ".off"; + std::ofstream off_stream(output_filename.str().c_str()); + + if (p_complex) + { + tc.export_to_off( + *p_complex, off_stream, + p_simpl_to_color_in_red, + p_simpl_to_color_in_green, + p_simpl_to_color_in_blue); + } + else + { +#ifdef CGAL_ALPHA_TC + TC::Simplicial_complex complex; + tc.export_TC(complex, false); + tc.export_to_off( + complex, off_stream, + p_simpl_to_color_in_red, + p_simpl_to_color_in_green, + p_simpl_to_color_in_blue); +#else + tc.export_to_off( + off_stream, color_inconsistencies, + p_simpl_to_color_in_red, + p_simpl_to_color_in_green, + p_simpl_to_color_in_blue); +#endif + } + return true; + } + return false; +} + +void make_tc(std::vector &points, + int intrinsic_dim, + double sparsity = 0., + bool perturb = true, + bool add_high_dim_simpl = false, + bool collapse = false, + double time_limit_for_perturb = 0., const char *input_name = "tc") { + // CJTODO TEMP TEST + //TC::Simplicial_complex compl; + //{std::size_t ss[] = {0, 1, 2}; compl.add_simplex(std::set(ss, ss + 3)); } + //{std::size_t ss[] = {0, 2, 3}; compl.add_simplex(std::set(ss, ss + 3)); } + //{std::size_t ss[] = {0, 3, 4}; compl.add_simplex(std::set(ss, ss + 3)); } + //{std::size_t ss[] = {0, 4, 1}; compl.add_simplex(std::set(ss, ss + 3)); } + //{std::size_t ss[] = {0, 5, 6}; compl.add_simplex(std::set(ss, ss + 3)); } + //compl.is_pure_pseudomanifold(2, 7, false, 10); + + //TC::Simplicial_complex compl; + //{std::size_t ss[] = {0, 1, 2, 5}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 2, 3, 5}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 3, 4, 5}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 4, 1, 5}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 1, 2, 6}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 2, 3, 6}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 3, 4, 6}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 4, 1, 6}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 4, 7, 8}; compl.add_simplex(std::set(ss, ss + 4)); } + //compl.is_pure_pseudomanifold(3, 9, false, 10); + // /CJTODO TEMP TEST + + //=========================================================================== + // Init + //=========================================================================== Kernel k; Wall_clock_timer t; + // Get input_name_stripped std::string input_name_stripped(input_name); size_t slash_index = input_name_stripped.find_last_of('/'); if (slash_index == std::string::npos) @@ -160,6 +243,9 @@ void make_tc(std::vector &points, int intrinsic_dim, std::vector points_not_sparse = points; #endif + //=========================================================================== + // Sparsify point set if requested + //=========================================================================== if (sparsity != 0.) { std::size_t num_points_before = points.size(); @@ -167,10 +253,14 @@ void make_tc(std::vector &points, int intrinsic_dim, std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; } - + CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); + //=========================================================================== + // Compute Tangential Complex + //=========================================================================== + #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM TC tc(points.begin(), points.end(), sparsity, intrinsic_dim, points_not_sparse.begin(), points_not_sparse.end(), k); @@ -183,8 +273,10 @@ void make_tc(std::vector &points, int intrinsic_dim, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - // CJTODO TEMP =========================== - { + //=========================================================================== + // CJTODO TEMP + //=========================================================================== + /*{ TC::Simplicial_complex complex; int max_dim = tc.export_TC(complex, false); complex.display_stats(); @@ -204,141 +296,191 @@ void make_tc(std::vector &points, int intrinsic_dim, std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(complex, off_stream); } - std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces; - bool pure_manifold = complex.is_pure_manifold( - intrinsic_dim, false, 1, - &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); + std::size_t num_wrong_dim_simplices, + num_wrong_number_of_cofaces, + num_unconnected_stars; + bool pure_manifold = complex.is_pure_pseudomanifold( + intrinsic_dim, tc.number_of_vertices(), false, 1, + &num_wrong_dim_simplices, &num_wrong_number_of_cofaces, + &num_unconnected_stars); complex.display_stats(); } - - return; + return;*/ // CJTODO TEMP =========================== //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); - double export_before_time = -1.; - if (intrinsic_dim <= 3) - { - t.reset(); - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true); - export_before_time = t.elapsed(); t.reset(); - } - - - + //=========================================================================== + // Export to OFF + //=========================================================================== + t.reset(); + double export_before_time = + (export_to_off(tc, input_name_stripped, "_BEFORE_FIX") ? t.elapsed() : -1); t.reset(); - unsigned int num_fix_steps; - std::size_t initial_num_inconsistent_local_tr; - std::size_t best_num_inconsistent_local_tr; - std::size_t final_num_inconsistent_local_tr; - CGAL::Fix_inconsistencies_status fix_ret = tc.fix_inconsistencies( - num_fix_steps, initial_num_inconsistent_local_tr, - best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, - time_limit_for_fix); - double fix_time = t.elapsed(); t.reset(); - - CGAL_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", - initial_num_inconsistent_local_tr); - CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", - best_num_inconsistent_local_tr); - CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", - final_num_inconsistent_local_tr); - double export_after_fix_time = -1.; - if (intrinsic_dim <= 3) + unsigned int num_perturb_steps = 0; + double perturb_time = -1; + double export_after_perturb_time = -1.; + CGAL::Fix_inconsistencies_status perturb_ret = CGAL::FIX_NOT_PERFORMED; + if (perturb) { + //========================================================================= + // Try to fix inconsistencies by perturbing points + //========================================================================= t.reset(); - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_AFTER_FIX.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true); - export_after_fix_time = t.elapsed(); t.reset(); + std::size_t initial_num_inconsistent_local_tr; + std::size_t best_num_inconsistent_local_tr; + std::size_t final_num_inconsistent_local_tr; + perturb_ret = tc.fix_inconsistencies( + num_perturb_steps, initial_num_inconsistent_local_tr, + best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, + time_limit_for_perturb); + perturb_time = t.elapsed(); t.reset(); + + CGAL_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", + initial_num_inconsistent_local_tr); + CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", + best_num_inconsistent_local_tr); + CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", + final_num_inconsistent_local_tr); + + //========================================================================= + // Export to OFF + //========================================================================= + t.reset(); + bool exported = export_to_off(tc, input_name_stripped, "_AFTER_FIX", true); + double export_after_perturb_time = (exported ? t.elapsed() : -1); + t.reset(); + } + else + { + CGAL_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", "N/A"); + CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", "N/A"); + CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", "N/A"); } - t.reset(); - // Try to solve the remaining inconstencies - tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); - double fix2_time = t.elapsed(); t.reset(); - TC::Simplicial_complex complex; - int max_dim = tc.export_TC(complex, false); - std::set > not_delaunay_simplices; - /*if (ambient_dim <= 4) - { - tc.check_if_all_simplices_are_in_the_ambient_delaunay( - &complex, true, ¬_delaunay_simplices); - }*/ - + int max_dim = -1; + double fix2_time = -1; double export_after_fix2_time = -1.; - if (intrinsic_dim <= 3) + TC::Simplicial_complex complex; + if (add_high_dim_simpl) { + //========================================================================= + // Try to fix inconsistencies by adding higher-dimension simplices + //========================================================================= t.reset(); - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_AFTER_FIX2.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(complex, off_stream, ¬_delaunay_simplices); - export_after_fix2_time = t.elapsed(); t.reset(); - } - - // Collapse - //complex.collapse(max_dim); + // Try to solve the remaining inconstencies + tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + fix2_time = t.elapsed(); t.reset(); + max_dim = tc.export_TC(complex, false); + /*std::set > not_delaunay_simplices; + if (ambient_dim <= 4) + { + tc.check_if_all_simplices_are_in_the_ambient_delaunay( + &complex, true, ¬_delaunay_simplices); + }*/ - double export_after_collapse_time = -1.; - if (intrinsic_dim <= 3) - { + //========================================================================= + // Export to OFF + //========================================================================= + t.reset(); + bool exported = export_to_off( + tc, input_name_stripped, "_AFTER_FIX2", false, &complex); + double export_after_fix2_time = (exported ? t.elapsed() : -1); t.reset(); - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_AFTER_COLLAPSE.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(complex, off_stream); - export_after_collapse_time = t.elapsed(); t.reset(); } - std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces; - bool pure_manifold = complex.is_pure_manifold( - intrinsic_dim, false, 0, - &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); + else + { + max_dim = tc.export_TC(complex, false); + } complex.display_stats(); + + //=========================================================================== + // Collapse + //=========================================================================== + std::cerr << max_dim << std::endl; + if (collapse) + complex.collapse(max_dim); + + //=========================================================================== + // Is the result a pure pseudomanifold? + //=========================================================================== + std::size_t num_wrong_dim_simplices, + num_wrong_number_of_cofaces, + num_unconnected_stars; + std::set > wrong_dim_simplices; + std::set > wrong_number_of_cofaces_simplices; + std::set > unconnected_stars_simplices; + bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold( + intrinsic_dim, tc.number_of_vertices(), false, 1, + &num_wrong_dim_simplices, &num_wrong_number_of_cofaces, + &num_unconnected_stars, + &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, + &unconnected_stars_simplices); + + // Stats about the simplices + complex.display_stats(); + + //=========================================================================== + // Export to OFF + //=========================================================================== + t.reset(); + bool exported = export_to_off( + tc, input_name_stripped, "_AFTER_COLLAPSE", false, &complex, + &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, + &unconnected_stars_simplices); + std::cerr + << " OFF colors:" << std::endl + << " * Red: wrong dim simplices" << std::endl + << " * Green: wrong number of cofaces simplices" << std::endl + << " * Blue: not-connected stars" << std::endl; + double export_after_collapse_time = (exported ? t.elapsed() : -1); + t.reset(); + + //=========================================================================== + // Display info + //=========================================================================== std::cerr << std::endl << "================================================" << std::endl << "Number of vertices: " << tc.number_of_vertices() << std::endl - << "Pure manifold: " << (pure_manifold ? "YES" : "NO") << std::endl + << "Pure pseudomanifold: " << (is_pure_pseudomanifold ? "YES" : "NO") << std::endl << "Computation times (seconds): " << std::endl - << " * Tangential complex: " << init_time + computation_time - << std::endl + << " * Tangential complex: " << init_time + computation_time << std::endl << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl - << " * Export to OFF (before fix): " << export_before_time << std::endl - << " * Fix inconsistencies 1: " << fix_time - << " (" << num_fix_steps << " steps) ==> " - << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl + << " * Export to OFF (before perturb): " << export_before_time << std::endl + << " * Fix inconsistencies 1: " << perturb_time + << " (" << num_perturb_steps << " steps) ==> " + << (perturb_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl << " * Fix inconsistencies 2: " << fix2_time << std::endl - << " * Export to OFF (after fix): " << export_after_fix_time << std::endl + << " * Export to OFF (after perturb): " << export_after_perturb_time << std::endl << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl << " * Export to OFF (after collapse): " << export_after_collapse_time << std::endl << "================================================" << std::endl << std::endl; - - CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); - CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); - CGAL_TC_SET_PERFORMANCE_DATA("Fix1_successful", - (fix_ret == CGAL::TC_FIXED ? "Y" : "N")); - CGAL_TC_SET_PERFORMANCE_DATA("Fix1_time", fix_time); - CGAL_TC_SET_PERFORMANCE_DATA("Fix1_steps", num_fix_steps); - CGAL_TC_SET_PERFORMANCE_DATA("Fix2_pure_manifold", - (pure_manifold ? "Y" : "N")); - CGAL_TC_SET_PERFORMANCE_DATA("Fix2_num_wrong_number_of_cofaces", - num_wrong_number_of_cofaces); - CGAL_TC_SET_PERFORMANCE_DATA("Fix2_time", fix2_time); - CGAL_TC_SET_PERFORMANCE_DATA("Info", ""); + + //=========================================================================== + // Export info + //=========================================================================== + CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); + CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); + CGAL_TC_SET_PERFORMANCE_DATA("Perturb_successful", + (perturb_ret == CGAL::TC_FIXED ? "Y" : "N")); + CGAL_TC_SET_PERFORMANCE_DATA("Perturb_time", perturb_time); + CGAL_TC_SET_PERFORMANCE_DATA("Perturb_steps", num_perturb_steps); + CGAL_TC_SET_PERFORMANCE_DATA("Add_higher_dim_simpl_time", fix2_time); + CGAL_TC_SET_PERFORMANCE_DATA("Result_pure_pseudomanifold", + (is_pure_pseudomanifold ? "Y" : "N")); + CGAL_TC_SET_PERFORMANCE_DATA("Result_num_wrong_dim_simplices", + num_wrong_dim_simplices); + CGAL_TC_SET_PERFORMANCE_DATA("Result_num_wrong_number_of_cofaces", + num_wrong_number_of_cofaces); + CGAL_TC_SET_PERFORMANCE_DATA("Result_num_unconnected_stars", + num_unconnected_stars); + CGAL_TC_SET_PERFORMANCE_DATA("Info", ""); } int main() @@ -406,7 +548,8 @@ int main() int ambient_dim; int intrinsic_dim; double sparsity; - double time_limit_for_fix; + char perturb, add_high_dim_simpl, collapse; + double time_limit_for_perturb; int num_iteration; sstr >> input; sstr >> param1; @@ -416,7 +559,10 @@ int main() sstr >> ambient_dim; sstr >> intrinsic_dim; sstr >> sparsity; - sstr >> time_limit_for_fix; + sstr >> perturb; + sstr >> add_high_dim_simpl; + sstr >> collapse; + sstr >> time_limit_for_perturb; sstr >> num_iteration; for (int j = 0 ; j < num_iteration ; ++j) @@ -490,7 +636,8 @@ int main() if (!points.empty()) { make_tc(points, intrinsic_dim, sparsity, - time_limit_for_fix, input.c_str()); + perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', + time_limit_for_perturb, input.c_str()); std::cerr << "TC #" << i++ << " done." << std::endl; std::cerr << std::endl << "---------------------------------" From f5e4f541c6a3edab433a311c4f64d45c51dcbc64 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 16:50:54 +0200 Subject: [PATCH 252/487] Added possibility to add noise in the point on sphere generator --- .../test/Tangential_complex/test_utilities.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 1eb2e3ad57d..14e1617ef4d 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -287,9 +287,12 @@ std::vector generate_points_on_moment_curve( template std::vector generate_points_on_sphere_d( - std::size_t num_points, int dim, double radius) + std::size_t num_points, int dim, double radius, + double radius_noise_percentage = 0.) { typedef typename Kernel::Point_d Point; + Kernel k; + CGAL::Random rng; CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector points; points.reserve(num_points); @@ -299,6 +302,20 @@ std::vector generate_points_on_sphere_d( for (std::size_t i = 0 ; i < num_points ; ) { Point p = *generator++; + if (radius_noise_percentage > 0.) + { + double radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage)/100., + (100. + radius_noise_percentage)/100.); + + typename Kernel::Point_to_vector_d k_pt_to_vec = + k.point_to_vector_d_object(); + typename Kernel::Vector_to_point_d k_vec_to_pt = + k.vector_to_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + k.scaled_vector_d_object(); + p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio)); + } #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) ++i; From bee9976153ce2b492e9133e2580173cecc0a75d5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 16:51:35 +0200 Subject: [PATCH 253/487] Added get_simplices_matching_test() + added checks in add_simplex --- .../Tangential_complex/Simplicial_complex.h | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index dac05d35a89..efd3e7646a0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -34,6 +34,8 @@ #include #include +#include + namespace CGAL { namespace Tangential_complex_ { @@ -43,8 +45,44 @@ public: typedef std::set Simplex; typedef std::set Simplex_range; - void add_simplex(const std::set &s) + void add_simplex( + const std::set &s, bool perform_checks = true) { + if (perform_checks) + { + unsigned int num_pts = static_cast(s.size()); + std::vector to_erase; + bool check_higher_dim_simpl = true; + for (Complex::iterator it_simplex = m_complex.begin(), + it_simplex_end = m_complex.end() ; + it_simplex != it_simplex_end ; + ++it_simplex) + { + // Check if the simplex is not already in a higher dim simplex + if (check_higher_dim_simpl + && it_simplex->size() > num_pts + && std::includes(it_simplex->begin(), it_simplex->end(), + s.begin(), s.end())) + { + // No need to insert it, then + return; + } + // Check if the simplex includes some lower-dim simplices + if (it_simplex->size() < num_pts + && std::includes(s.begin(), s.end(), + it_simplex->begin(), it_simplex->end())) + { + to_erase.push_back(it_simplex); + // We don't need to check higher-sim simplices any more + check_higher_dim_simpl = false; + } + } + for (std::vector::const_iterator it= to_erase.begin(); + it != to_erase.end() ; ++it) + { + m_complex.erase(*it); + } + } m_complex.insert(s); } @@ -58,6 +96,19 @@ public: m_complex.clear(); } + template + void get_simplices_matching_test(Test test, Output_it out) + { + for (Complex::const_iterator it_simplex = m_complex.begin(), + it_simplex_end = m_complex.end() ; + it_simplex != it_simplex_end ; + ++it_simplex) + { + if (test(*it_simplex)) + *out++ = *it_simplex; + } + } + // When a simplex S has only one co-face C, we can remove S and C // without changing the topology void collapse(int max_simplex_dim, bool quiet = false) From e6cb33d97e0877017377ef33fbadab46c04d0e6c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 16:52:51 +0200 Subject: [PATCH 254/487] Fixed indentation + typo --- .../include/CGAL/Tangential_complex.h | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2f88a7b36cc..c1509942497 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -2820,36 +2820,36 @@ next_face: complex.simplex_range().begin(); typename Simplex_range::const_iterator it_s_end = complex.simplex_range().end(); - // For each triangulation + // For each simplex for ( ; it_s != it_s_end ; ++it_s) { Simplex c = *it_s; - int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue - if (p_simpl_to_color_in_red && - std::find( - p_simpl_to_color_in_red->begin(), - p_simpl_to_color_in_red->end(), - c) != p_simpl_to_color_in_red->end()) - { - color_simplex = 1; - } - else if (p_simpl_to_color_in_green && - std::find( - p_simpl_to_color_in_green->begin(), - p_simpl_to_color_in_green->end(), - c) != p_simpl_to_color_in_green->end()) - { - color_simplex = 2; - } - else if (p_simpl_to_color_in_blue && - std::find( - p_simpl_to_color_in_blue->begin(), - p_simpl_to_color_in_blue->end(), - c) != p_simpl_to_color_in_blue->end()) - { - color_simplex = 3; - } + int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue + if (p_simpl_to_color_in_red && + std::find( + p_simpl_to_color_in_red->begin(), + p_simpl_to_color_in_red->end(), + c) != p_simpl_to_color_in_red->end()) + { + color_simplex = 1; + } + else if (p_simpl_to_color_in_green && + std::find( + p_simpl_to_color_in_green->begin(), + p_simpl_to_color_in_green->end(), + c) != p_simpl_to_color_in_green->end()) + { + color_simplex = 2; + } + else if (p_simpl_to_color_in_blue && + std::find( + p_simpl_to_color_in_blue->begin(), + p_simpl_to_color_in_blue->end(), + c) != p_simpl_to_color_in_blue->end()) + { + color_simplex = 3; + } // Gather the triangles here typedef std::vector Triangles; From 0eff36145c52d596df747b013d86f5a53afa8bda Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 16:53:27 +0200 Subject: [PATCH 255/487] Added a colored export just before collapse --- .../Tangential_complex/benchmark_tc.cpp | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ae2b8310809..ca1513be303 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -127,6 +127,27 @@ protected: XML_exporter::Element_with_map m_current_element; }; +class Test_dim +{ +public: + Test_dim( + int min_allowed_dim = 0, + int max_allowed_dim = std::numeric_limits::max()) + : m_min_allowed_dim(min_allowed_dim), m_max_allowed_dim(max_allowed_dim) + {} + + template + bool operator()(Simplex const& s) + { + return s.size() - 1 >= m_min_allowed_dim + && s.size() - 1 <= m_max_allowed_dim; + } + +private: + int m_min_allowed_dim; + int m_max_allowed_dim; +}; + template bool export_to_off( TC const& tc, @@ -395,11 +416,19 @@ void make_tc(std::vector &points, } complex.display_stats(); + + // Export to OFF with higher-dim simplices colored + std::set > higher_dim_simplices; + complex.get_simplices_matching_test( + Test_dim(intrinsic_dim + 1), + std::inserter(higher_dim_simplices, higher_dim_simplices.begin())); + export_to_off( + tc, input_name_stripped, "_BEFORE_COLLAPSE", false, &complex, + &higher_dim_simplices); //=========================================================================== // Collapse //=========================================================================== - std::cerr << max_dim << std::endl; if (collapse) complex.collapse(max_dim); @@ -409,7 +438,7 @@ void make_tc(std::vector &points, std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces, num_unconnected_stars; - std::set > wrong_dim_simplices; + std::set > wrong_dim_simplices; std::set > wrong_number_of_cofaces_simplices; std::set > unconnected_stars_simplices; bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold( @@ -607,7 +636,8 @@ int main() { points = generate_points_on_sphere_d( num_points, ambient_dim, - std::atof(param1.c_str())); + std::atof(param1.c_str()), + std::atof(param2.c_str())); } else if (input == "generate_klein_bottle_3D") { From 8ba0ff256672aeca2bf2af5a98ccabcee505cde8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 17:18:49 +0200 Subject: [PATCH 256/487] Updated script --- .../benchmark/Tangential_complex/benchmark_script.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index a26d5085ada..1b050e0eccf 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -15,7 +15,8 @@ #---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ #generate_sphere_d 0.302 - - 70 2 1 0.005 N N Y 60 1 #generate_sphere_d 0.5 - - 70 2 1 0.005 N N Y 60 1 -generate_klein_bottle_4D 40 15 - 130 4 2 0.2 N N Y 60 1 +generate_sphere_d 3 2 - 100 3 2 0.05 N N Y 60 1 +#generate_klein_bottle_4D 40 15 - 130 4 2 0.2 N N Y 60 1 #generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 Y Y Y 60 1 #Takes forever #------------------------------------------------------------------ From files -------------------------------------------------------------------------- From 5aedcaea15eb0c603ef6c6e42a44c52ce82d3613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 23 Apr 2015 15:36:06 +0200 Subject: [PATCH 257/487] Fix compilation issues (cherry picked from commit b02fdcb35398ba5d87ce7ae0523357e3f5d867a2) --- .../include/CGAL/Tangential_complex.h | 39 +++++++++---------- .../CGAL/Tangential_complex/utilities.h | 31 +++++++-------- .../test/Tangential_complex/test_utilities.h | 1 - 3 files changed, 33 insertions(+), 38 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c1509942497..075dbbde152 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -69,8 +69,10 @@ //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) #define CGAL_ALPHA_TC const double ALPHA = 0.3; +#ifdef CGAL_LINKED_WITH_TBB tbb::atomic ttt_star; // CJTODO TEMP tbb::atomic ttt_intersect; +#endif namespace CGAL { @@ -263,7 +265,7 @@ public: void compute_tangential_complex() { -#ifdef CGAL_TC_PROFILING +#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) Wall_clock_timer t; ttt_intersect = 0; ttt_star = 0; @@ -316,7 +318,7 @@ public: #endif } -#ifdef CGAL_TC_PROFILING +#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) std::cerr << "Tangential complex computed in " << t.elapsed() << " seconds." << std::endl; std::cerr << "Intersect: " << ((double)ttt_intersect)/1000000 << " s\n" @@ -1207,10 +1209,11 @@ private: typename Amb_RT_Traits::Dimension, Triangulation_vertex > > Amb_RT; + typedef typename Amb_RT::Weighted_point Amb_RT_Point; typedef typename Amb_RT::Vertex_handle Amb_RT_VH; typedef typename Amb_RT::Full_cell_handle Amb_RT_FCH; //typedef typename Amb_RT::Finite_full_cell_const_iterator Amb_FFC_it; - + typename Kernel::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object(); typename Kernel::Squared_distance_d k_sqdist = @@ -1330,7 +1333,7 @@ private: } else { - Tr_point c = k_power_center( + Amb_RT_Point c = k_power_center( boost::make_transform_iterator( cell->vertices_begin(), vertex_handle_to_point), @@ -1367,10 +1370,10 @@ private: } } -#ifdef CGAL_TC_PROFILING +#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) ttt_star += 1000000*t_star.elapsed(); #endif - + //*************************************************** // Parse the faces of the star and add the ones that are in the // restriction to alpha-Tp @@ -1488,8 +1491,8 @@ next_face: #endif bool does_intersect = does_voronoi_face_and_alpha_tangent_subspace_intersect( - m_points, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); -#ifdef CGAL_TC_PROFILING + m_points, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); +#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) ttt_intersect += 1000000*t_inters.elapsed(); #endif if (does_intersect) @@ -1599,12 +1602,10 @@ next_face: { if (normalize_basis) { - ts.push_back(normalize_vector( - constr_vec( - m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim), - m_k)); + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambient_dim); + ts.push_back(normalize_vector(v, m_k)); } else { @@ -1623,12 +1624,10 @@ next_face: { if (normalize_basis) { - p_orth_space_basis->push_back(normalize_vector( - constr_vec( - m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim), - m_k)); + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambient_dim); + p_orth_space_basis->push_back(normalize_vector(v, m_k)); } else { diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 173b161d5b0..531f3318c1b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -129,13 +129,11 @@ namespace Tangential_complex_ { // Modifies v in-place template - typename K::Vector_d & - normalize_vector( - typename K::Vector_d &v, - K const& k) + typename K::Vector_d& normalize_vector(typename K::Vector_d& v, + K const& k) { v = k.scaled_vector_d_object()( - v, FT(1)/CGAL::sqrt(k.squared_length_d_object()(v))); + v, typename K::FT(1)/CGAL::sqrt(k.squared_length_d_object()(v))); return v; } @@ -145,7 +143,6 @@ namespace Tangential_complex_ { std::vector const& input_basis, K const& k) { - typedef typename K::FT FT; typedef typename K::Vector_d Vector; typedef std::vector Basis; @@ -201,7 +198,7 @@ namespace Tangential_complex_ { } while (std::next_permutation(booleans.begin(), booleans.end())); } - // P: dual face in Delaunay triangulation (p0, p1, pn) + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P template @@ -216,7 +213,7 @@ namespace Tangential_complex_ { { // Notations: // Fv: Voronoi k-face - // Fd: dual, (D-k)-face of Delaunay (p0, p1, pn) + // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) typedef typename K::FT FT; typedef typename K::Point_d Point; @@ -244,11 +241,11 @@ namespace Tangential_complex_ { //=========== First set of equations =========== // For point pi in P - // 2(p0 - pi).x = p0 - pi + // 2(p0 - pi).x = p0^2 - pi^2 Point const& p0 = center_pt; FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); - for (Indexed_point_range::const_iterator it_p = P.begin(), - it_p_end = P.end() ; + for (typename Indexed_point_range::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { Point const& pi = all_points[*it_p]; @@ -286,9 +283,9 @@ namespace Tangential_complex_ { //=========== Second set of equations =========== // For each point qi in Q - // 2(qi - p0).x <= qi - p0 - for (Indexed_point_range_2::const_iterator it_q = Q.begin(), - it_q_end = Q.end() ; + // 2(qi - p0).x <= qi^2 - p0^2 + for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; it_q != it_q_end ; ++it_q) { Point const& qi = all_points[*it_q]; @@ -306,9 +303,9 @@ namespace Tangential_complex_ { // For each vector of OSB // bi.x <= bi.p + alpha // -bi.x <= -bi.p + alpha - for (Vector_range::const_iterator it_osb = - orthogonal_subspace_basis.begin(), - it_osb_end = orthogonal_subspace_basis.end() ; + for (typename Vector_range::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; it_osb != it_osb_end ; ++it_osb) { Vector const& bi = *it_osb; diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 14e1617ef4d..6b0c8c89b4c 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -135,7 +135,6 @@ sparsify_point_set( const Kernel &k, Point_container const& input_pts, typename Kernel::FT min_squared_dist) { - 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::INS_iterator INS_iterator; From b3bd06aa211d025a8cb90bd7c03994d2fd102424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 23 Apr 2015 15:38:28 +0200 Subject: [PATCH 258/487] Fix trailing whitespace (cherry picked from commit 502ab45855e9d5c42660be842f8e27cbe94bea3e) --- .../include/CGAL/Tangential_complex.h | 232 +++++++++--------- .../CGAL/Tangential_complex/utilities.h | 20 +- .../test/Tangential_complex/test_utilities.h | 16 +- 3 files changed, 134 insertions(+), 134 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 075dbbde152..c7ccdecb53d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -89,7 +89,7 @@ public: {} operator std::size_t() { return m_data; } operator std::size_t() const { return m_data; } - + private: std::size_t m_data; }; @@ -193,7 +193,7 @@ class Tangential_complex typedef typename std::vector Tr_container; typedef typename std::vector Vectors; - // An Incident_simplex is the list of the vertex indices + // An Incident_simplex is the list of the vertex indices // except the center vertex typedef std::set Incident_simplex; typedef std::vector Star; @@ -241,7 +241,7 @@ public: {} /// Destructor - ~Tangential_complex() + ~Tangential_complex() { #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) @@ -325,7 +325,7 @@ public: << "Star: " << ((double)ttt_star)/1000000 << " s\n"; #endif } - + void estimate_intrinsic_dimension() { // Kernel functors @@ -389,8 +389,8 @@ public: if (boost::is_convertible::value) { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), - Compute_tangent_triangulation(*this, - true) //tangent_spaces_are_already_computed + Compute_tangent_triangulation(*this, + true) //tangent_spaces_are_already_computed ); } // Sequential @@ -403,12 +403,12 @@ public: compute_alpha_tangent_triangulation(i, ALPHA, true); // tangent_spaces_are_already_computed #else - compute_tangent_triangulation(i, + compute_tangent_triangulation(i, true); // tangent_spaces_are_already_computed #endif } } - + #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex refreshed in " << t.elapsed() @@ -418,10 +418,10 @@ public: // time_limit in seconds: 0 = no fix to do, < 0 = no time limit Fix_inconsistencies_status fix_inconsistencies( - unsigned int &num_steps, + unsigned int &num_steps, std::size_t &initial_num_inconsistent_local_tr, - std::size_t &best_num_inconsistent_local_tr, - std::size_t &final_num_inconsistent_local_tr, + std::size_t &best_num_inconsistent_local_tr, + std::size_t &final_num_inconsistent_local_tr, double time_limit = -1.) { if (time_limit == 0.) @@ -429,7 +429,7 @@ public: Wall_clock_timer t; - typename Kernel::Point_drop_weight_d drop_w = + typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); #ifdef CGAL_TC_VERBOSE @@ -460,7 +460,7 @@ public: while (!done) { std::size_t num_inconsistent_local_tr = 0; - + #ifdef CGAL_TC_PROFILING Wall_clock_timer t_fix_step; #endif @@ -484,7 +484,7 @@ public: { for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) { - num_inconsistent_local_tr += + num_inconsistent_local_tr += (try_to_solve_inconsistencies_in_a_local_triangulation(i) ? 1 : 0); } } @@ -503,7 +503,7 @@ public: number_of_inconsistent_simplices(false); std::cerr << std::endl - << "==========================================================" + << "==========================================================" << std::endl << "Inconsistencies (detailed stats):\n" << " * Number of vertices: " << m_points.size() << std::endl @@ -512,12 +512,12 @@ public: << " - Total number of simplices in stars (incl. duplicates): " << stats_before.first << std::endl << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second + << stats_before.second << " (" << 100. * stats_before.second / stats_before.first << "%)" << std::endl << " * Num inconsistent local triangulations: " - << num_inconsistent_local_tr - << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" + << num_inconsistent_local_tr + << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl << std::endl << " * AFTER fix_inconsistencies:" << std::endl @@ -540,7 +540,7 @@ public: << std::endl << "fix_inconsistencies():\n" << " * " << m_points.size() << " vertices" << std::endl - << " * " << num_inconsistent_local_tr + << " * " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << " inconsistent triangulations encountered" << std::endl << "==========================================================" @@ -598,7 +598,7 @@ public: // Don't export infinite cells if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; - + std::set c = *it_inc_simplex; c.insert(idx); // Add the missing index @@ -675,7 +675,7 @@ public: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - inconsistencies_found = + inconsistencies_found = check_and_solve_inconsistencies_by_adding_higher_dim_simplices( idx, *it_inc_simplex); @@ -683,10 +683,10 @@ public: // CJTODO: optimize? if (inconsistencies_found) break; - } + } } while (inconsistencies_found); } - + // CJTODO TEMP std::pair stats_after = number_of_inconsistent_simplices(false); @@ -699,7 +699,7 @@ public: << 100. * stats_after.second / stats_after.first << "%" << std::endl; } - + std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, std::set > const *p_simpl_to_color_in_red = NULL, @@ -711,7 +711,7 @@ public: os, false, p_simpl_to_color_in_red, p_simpl_to_color_in_green, p_simpl_to_color_in_blue, &complex); } - + std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, std::set > const *p_simpl_to_color_in_red = NULL, @@ -816,9 +816,9 @@ public: for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; cit != ambient_dt.finite_full_cells_end() ; ++cit ) { - int lowest_dim = + int lowest_dim = (check_for_any_dimension_simplices ? 1 : m_intrinsic_dimension); - int highest_dim = + int highest_dim = (check_for_any_dimension_simplices ? m_ambient_dim : m_intrinsic_dimension); for (int dim = lowest_dim ; dim <= highest_dim ; ++dim) @@ -838,7 +838,7 @@ public: } //------------------------------------------------------------------------- - // If p_complex is NULL, parse the TC and + // If p_complex is NULL, parse the TC and // save its simplices into "stars_simplices" //------------------------------------------------------------------------- @@ -1012,12 +1012,12 @@ private: // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions const Point center_pt = compute_perturbed_point(i); - + // Estimate the tangent space if (!tangent_spaces_are_already_computed) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, &m_orth_spaces[i]); #else m_tangent_spaces[i] = compute_tangent_space(center_pt); @@ -1027,7 +1027,7 @@ private: else if (m_perturb_tangent_space[i]) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); #else m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); @@ -1075,7 +1075,7 @@ private: // ith point = p, which is already inserted if (neighbor_point_idx != i) { - // No need to lock the Mutex_for_perturb here since this will not be + // No need to lock the Mutex_for_perturb here since this will not be // called while other threads are perturbing the positions Point neighbor_pt; FT neighbor_weight; @@ -1089,7 +1089,7 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, neighbor_weight, center_pt, m_tangent_spaces[i], + neighbor_pt, neighbor_weight, center_pt, m_tangent_spaces[i], local_tr_traits); Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); @@ -1130,7 +1130,7 @@ private: FT sq_power_sphere_diam = 4*point_weight(c); if (!squared_star_sphere_radius_plus_margin - || sq_power_sphere_diam > + || sq_power_sphere_diam > *squared_star_sphere_radius_plus_margin) { squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; @@ -1147,7 +1147,7 @@ private: *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; #else squared_star_sphere_radius_plus_margin = CGAL::square( - CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2*m_half_sparsity); #endif } @@ -1162,7 +1162,7 @@ private: Star &star = m_stars[i]; star.clear(); int cur_dim_plus_1 = local_tr.current_dimension() + 1; - + std::vector incident_cells; local_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); @@ -1199,7 +1199,7 @@ private: bool verbose = false) { if (verbose) - std::cerr << "** Computing alpha tangent tri #" + std::cerr << "** Computing alpha tangent tri #" << i << " **" << std::endl; typedef Regular_triangulation_euclidean_traits Amb_RT_Traits; @@ -1222,7 +1222,7 @@ private: m_k.point_weight_d_object(); typename Kernel::Power_center_d k_power_center = m_k.power_center_d_object(); - + // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions const Point ¢er_pt = m_points[i]; @@ -1231,7 +1231,7 @@ private: if (!tangent_spaces_are_already_computed) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, &m_orth_spaces[i]); #else m_tangent_spaces[i] = compute_tangent_space(center_pt); @@ -1241,7 +1241,7 @@ private: else if (m_perturb_tangent_space[i]) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); #else m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); @@ -1254,13 +1254,13 @@ private: // Build a minimal triangulation in the tangent space // (we only need the star of p in the AMBIENT triangulation) //*************************************************** - + #ifdef CGAL_TC_PROFILING Wall_clock_timer t_star; #endif Amb_RT local_amb_tr(m_ambient_dim); - + // Insert p Weighted_point wp = m_k.construct_weighted_point_d_object()( center_pt, @@ -1293,7 +1293,7 @@ private: // ith point = p, which is already inserted if (neighbor_point_idx != i) { - // No need to lock the Mutex_for_perturb here since this will not be + // No need to lock the Mutex_for_perturb here since this will not be // called while other threads are perturbing the positions Weighted_point neighbor_wp = compute_perturbed_weighted_point(neighbor_point_idx); @@ -1344,7 +1344,7 @@ private: FT sq_power_sphere_diam = 4*k_point_weight(c); if (!squared_star_sphere_radius_plus_margin - || sq_power_sphere_diam > + || sq_power_sphere_diam > *squared_star_sphere_radius_plus_margin) { squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; @@ -1361,7 +1361,7 @@ private: *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; #else squared_star_sphere_radius_plus_margin = CGAL::square( - CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2*m_half_sparsity); #endif } @@ -1382,7 +1382,7 @@ private: Star &star = m_stars[i]; star.clear(); int cur_dim_plus_1 = m_ambient_dim + 1; - + std::vector incident_cells; local_amb_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); @@ -1423,7 +1423,7 @@ next_face: int current_dim = m_ambient_dim - 1; while (current_dim > 0) { - // Let's fill faces_and_neighbors[current_dim-1] + // Let's fill faces_and_neighbors[current_dim-1] // (stores the current_dim-faces) DT_faces_and_neighbors& cur_faces_and_nghb = faces_and_neighbors[current_dim-1]; @@ -1435,7 +1435,7 @@ next_face: it_k_p1_face != it_k_p1_face_end ; ++it_k_p1_face) { DT_face const& k_p1_face = it_k_p1_face->first; - + // Add each k faces to cur_faces_and_nghb std::size_t n = current_dim + 1; // Not +2 since 'i' is not stored std::vector booleans(n, false); @@ -1465,7 +1465,7 @@ next_face: current_dim = m_ambient_dim; while (current_dim > 0) { - // Remember: faces_and_neighbors[current_dim-1] stores + // Remember: faces_and_neighbors[current_dim-1] stores // the current_dim-faces DT_faces_and_neighbors const& cur_faces_and_nghb = faces_and_neighbors[current_dim-1]; @@ -1478,7 +1478,7 @@ next_face: Neighbor_vertices const& curr_neighbors = it_f->second; DT_face const& current_DT_face = it_f->first; - CGAL_assertion(static_cast(current_DT_face.size()) + CGAL_assertion(static_cast(current_DT_face.size()) == current_dim); // P: list of current_DT_face points (including 'i') @@ -1498,7 +1498,7 @@ next_face: if (does_intersect) { star.push_back(current_DT_face); - + // Clear all subfaces of current_DT_face from the maps for (int dim = current_dim - 1 ; dim > 0 ; --dim) { @@ -1561,7 +1561,7 @@ next_face: m_k.difference_of_vectors_d_object(); //typename Kernel::Translated_point_d transl = // m_k.translated_point_d_object(); - + #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM KNS_range kns_range = m_points_ds_for_tse.query_ANN( p, NUM_POINTS_FOR_PCA, false); @@ -1596,8 +1596,8 @@ next_face: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = m_ambient_dim - 1 ; - i >= m_ambient_dim - m_intrinsic_dimension ; + for (int i = m_ambient_dim - 1 ; + i >= m_ambient_dim - m_intrinsic_dimension ; --i) { if (normalize_basis) @@ -1618,8 +1618,8 @@ next_face: if (p_orth_space_basis) { - for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; - i >= 0 ; + for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; + i >= 0 ; --i) { if (normalize_basis) @@ -1647,7 +1647,7 @@ next_face: return ts; - + // CJTODO: this is only for a sphere in R^3 /*double tt1[3] = {-p[1] - p[2], p[0], p[0]}; double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], @@ -1710,7 +1710,7 @@ next_face: { typename Kernel::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); - + Weighted_point wp = k_constr_wp( #ifdef CGAL_TC_PERTURB_POSITION m_k.translated_point_d_object()(m_points[pt_idx], m_translations[pt_idx]), @@ -1741,7 +1741,7 @@ next_face: for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_point = k_transl( - global_point, + global_point, k_scaled_vec(tsb[i], coord(p, i))); } @@ -1905,7 +1905,7 @@ next_face: #ifdef CGAL_TC_PERTURB_WEIGHT m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); #endif - + #ifdef CGAL_TC_PERTURB_TANGENT_SPACE m_perturb_tangent_space[point_idx] = true; #endif @@ -1915,7 +1915,7 @@ next_face: # ifdef CGAL_TC_PERTURB_POSITION_GLOBAL typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); - CGAL::Random_points_on_sphere_d + CGAL::Random_points_on_sphere_d tr_point_on_sphere_generator(m_ambient_dim, 1); // Parallel # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) @@ -1931,7 +1931,7 @@ next_face: # endif # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - const Tr_traits &local_tr_traits = + const Tr_traits &local_tr_traits = m_triangulations[point_idx].tr().geom_traits(); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); @@ -1941,8 +1941,8 @@ next_face: m_k.construct_vector_d_object(); typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - - CGAL::Random_points_on_sphere_d + + CGAL::Random_points_on_sphere_d tr_point_on_sphere_generator(m_intrinsic_dimension, 1); Tr_point local_random_transl = @@ -1953,7 +1953,7 @@ next_face: for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_transl = k_transl( - global_transl, + global_transl, k_scaled_vec(tsb[i], m_half_sparsity*coord(local_random_transl, i)) ); } @@ -1979,7 +1979,7 @@ next_face: #ifdef CGAL_LINKED_WITH_TBB //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif - + Star const& star = m_stars[tr_index]; Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); @@ -2009,12 +2009,12 @@ next_face: { is_inconsistent = true; - for (std::set::const_iterator it = c.begin(); + for (std::set::const_iterator it = c.begin(); it != c.end() ; ++it) { perturb(*it); } - + # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif @@ -2030,7 +2030,7 @@ next_face: if (!is_simplex_consistent(c)) { is_inconsistent = true; - + std::size_t idx = tr_index; /*int k; do @@ -2048,7 +2048,7 @@ next_face: // We will try the other cells next time break; } - + //***************************************************************************** // STRATEGY 3: perturb all the points of the 1-star //***************************************************************************** @@ -2058,22 +2058,22 @@ next_face: if (!is_simplex_consistent(c)) { is_inconsistent = true; - + std::set the_1_star; - + Star::const_iterator it_inc_simplex = star.begin(); Star::const_iterator it_inc_simplex_end = star.end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { the_1_star.insert(it_inc_simplex->begin(), it_inc_simplex ->end()); } - - for (std::set::iterator it = the_1_star.begin() ; + + for (std::set::iterator it = the_1_star.begin() ; it != the_1_star.end() ; ++it) { perturb(*it); } - + # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif @@ -2087,7 +2087,7 @@ next_face: // closest points (to the power center of first the inconsistent cell) //***************************************************************************** #elif defined(CGAL_TC_PERTURB_N_CLOSEST_POINTS) - + // Inconsistent? if (!is_simplex_consistent(c)) { @@ -2098,7 +2098,7 @@ next_face: std::vector simplex_pts; simplex_pts.reserve(c.size()); - + Incident_simplex::const_iterator it_point_idx = c.begin(); Incident_simplex::const_iterator it_point_idx_end = c.end(); // For each point p of the simplex, we reproject it onto the tangent @@ -2126,9 +2126,9 @@ next_face: m_points[tr_index], m_tangent_spaces[tr_index], local_tr_traits); - + KNS_range kns_range = m_points_ds.query_ANN( - global_center, + global_center, CGAL_TC_NUMBER_OF_PERTURBED_POINTS(m_intrinsic_dimension)); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; @@ -2138,8 +2138,8 @@ next_face: neighbors.push_back(nn_it->first); } - for (std::vector::iterator it = neighbors.begin(); - it != neighbors.end() ; + for (std::vector::iterator it = neighbors.begin(); + it != neighbors.end() ; ++it) { perturb(*it); @@ -2244,7 +2244,7 @@ next_face: incident_simplex.erase(index); // Remove the center index Star &star = m_stars[index]; - + std::set::const_iterator it_point_idx = simplex.begin(); std::set::const_iterator it_point_idx_end = simplex.end(); for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) @@ -2256,14 +2256,14 @@ next_face: // Temporarily remove this index incident_simplex.erase(*it_point_idx); // Erase incident_simplex from star - star.erase(std::remove(star.begin(), star.end(), incident_simplex), + star.erase(std::remove(star.begin(), star.end(), incident_simplex), star.end()); incident_simplex.insert(*it_point_idx); } star.push_back(incident_simplex); } - + // Solves one inconsistency // "inconsistent_simplex" must contain p_idx and q_idx // "inconsistent_simplex" must be in star(p) but not in star(q) @@ -2319,16 +2319,16 @@ next_face: const Point pt_p = compute_perturbed_point(p_idx); const Point pt_q = compute_perturbed_point(q_idx); - std::set::const_iterator it_point_idx = + std::set::const_iterator it_point_idx = inconsistent_simplex.begin(); - std::set::const_iterator it_point_idx_end = + std::set::const_iterator it_point_idx_end = inconsistent_simplex.end(); // For each point of the simplex, we reproject it onto the tangent // space. Could be optimized since it's already been computed before. for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { const Weighted_point wp = compute_perturbed_weighted_point(*it_point_idx); - // No need to lock the Mutex_for_perturb here since this will not be + // No need to lock the Mutex_for_perturb here since this will not be // called while other threads are perturbing the positions simplex_pts_in_Tp.push_back(project_point_and_compute_weight( wp, pt_p, m_tangent_spaces[p_idx], q_tr_traits)); @@ -2344,7 +2344,7 @@ next_face: FT circumsphere_sqradius_p = tr_point_weight(Cp); FT circumsphere_sqradius_q = tr_point_weight(Cq); #ifdef CGAL_TC_PERTURB_WEIGHT - FT squared_circumsphere_radius_q_plus_margin = + FT squared_circumsphere_radius_q_plus_margin = circumsphere_sqradius_q + 4*m_sq_half_sparsity; #else FT squared_circumsphere_radius_q_plus_margin = CGAL::square( @@ -2381,7 +2381,7 @@ next_face: //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_Cp_power_sqdist <= FT(0) - && inconsistent_simplex.find(neighbor_point_idx) == + && inconsistent_simplex.find(neighbor_point_idx) == inconsistent_simplex.end()) { std::cerr << "Warning: " << neighbor_point_idx << " is inside Cp with power dist " << point_to_Cp_power_sqdist << "\n"; @@ -2410,7 +2410,7 @@ next_face: global_Cq, compute_perturbed_weighted_point(neighbor_point_idx)); // If the point is ACTUALLY "inside" S if (point_to_Cq_power_sqdist <= FT(0) - && inconsistent_simplex.find(neighbor_point_idx) == + && inconsistent_simplex.find(neighbor_point_idx) == inconsistent_simplex.end()) { inside_pt_indices.push_back(neighbor_point_idx); @@ -2421,7 +2421,7 @@ next_face: typename Tr_traits::Orientation_d orient = q_tr_traits.orientation_d_object(); Orientation o = orient(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); auto p = project_point_and_compute_weight( - compute_perturbed_weighted_point(neighbor_point_idx), + compute_perturbed_weighted_point(neighbor_point_idx), pt_q, m_tangent_spaces[q_idx], q_tr_traits); auto sid = (o == NEGATIVE ? side(simplex_pts_in_Tq.rbegin(), simplex_pts_in_Tq.rend(), p) @@ -2440,9 +2440,9 @@ next_face: } }*/ } - CGAL_assertion_msg(!inside_pt_indices.empty(), + CGAL_assertion_msg(!inside_pt_indices.empty(), "There should be at least one vertex inside the sphere"); - + // CJTODO TEMP DEBUG /*if (inside_pt_indices.empty()) { @@ -2461,7 +2461,7 @@ next_face: // CJTODO TEMP DEBUG if (inside_pt_indices.size() > 1) { - std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " + std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " << inconsistent_simplex.size() - 1 << " simplex\n"; } @@ -2474,13 +2474,13 @@ next_face: //----------------------------------------------------------------------- //5. For each ti, compute the sphere that goes through // p, q, r1, r2..., ri and ti whose center is on (cp, cq) - // We're looking for a point on (Cp, Cq) at equal distance from p and + // We're looking for a point on (Cp, Cq) at equal distance from p and // ti. // The center of the sphere is then: Cp + a(Cq - Cp) // where a = (sqdist(Cp,ti) - sqdist(Cp,p)) / (2*(Cq-Cp).(ti-p)) //6. Keep point ti such as dist(cp, ci) is the smallest //----------------------------------------------------------------------- - + FT min_a = std::numeric_limits::max(); for (auto idx : inside_pt_indices) // CJTODO: C++11 { @@ -2493,11 +2493,11 @@ next_face: const Weighted_point p_w = compute_perturbed_weighted_point(p_idx); const Weighted_point cp_w0 = k_constr_wp(k_drop_w(global_Cp), FT(0)); const Weighted_point wp_w0 = k_constr_wp(k_drop_w(global_Cq), FT(0)); - FT a = + FT a = (k_power_dist(cp_w0, ti_w) - k_power_dist(cp_w0, p_w)) / (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); #else - FT a = + FT a = (k_sqdist(cp, ti) - k_sqdist(cp, pt_p)) / (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); #endif @@ -2508,7 +2508,7 @@ next_face: inside_point_idx = idx; } } - + // CJTODO TEMP ==================== /*{ typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); @@ -2535,7 +2535,7 @@ next_face: //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_C_power_sqdist <= FT(-0.000001) - && inconsistent_simplex.find(neighbor_point_idx) == + && inconsistent_simplex.find(neighbor_point_idx) == inconsistent_simplex.end()) { std::cerr << "Warning: " << neighbor_point_idx << " is inside C with power dist " << point_to_C_power_sqdist << "\n"; @@ -2554,14 +2554,14 @@ next_face: //------------------------------------------------------------------------- std::set new_simplex = inconsistent_simplex; new_simplex.insert(inside_point_idx); - + it_point_idx = new_simplex.begin(); it_point_idx_end = new_simplex.end(); for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { insert_higher_dim_simplex_into_star(*it_point_idx, new_simplex); } - // CJTODO: call + // CJTODO: call // check_and_solve_inconsistencies_by_adding_higher_dim_simplices // recursively? Not sure, since the star will be parsed again from // the beginning @@ -2576,7 +2576,7 @@ next_face: bool inconsistencies_found = false; // Don't check infinite simplices - if (*incident_simplex.rbegin() + if (*incident_simplex.rbegin() == std::numeric_limits::max()) return false; @@ -2639,9 +2639,9 @@ next_face: std::stringstream color; //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; color << 128 << " " << 128 << " " << 128; - + // Gather the triangles here, with an int telling its color - typedef std::vector, int> > + typedef std::vector, int> > Star_using_triangles; Star_using_triangles star_using_triangles; @@ -2688,7 +2688,7 @@ next_face: color_simplex = 3; } } - + // If m_intrinsic_dimension = 1, each point is output two times, // so we need to multiply each index by 2 // And if only 2 vertices, add a third one (each vertex is duplicated in @@ -2718,7 +2718,7 @@ next_face: { std::set triangle; std::set::iterator it = c.begin(); - for (int i = 0; it != c.end() ; ++i, ++it) + for (int i = 0; it != c.end() ; ++i, ++it) { if (booleans[i]) triangle.insert(*it); @@ -2730,17 +2730,17 @@ next_face: } // For each cell - Star_using_triangles::const_iterator it_simplex = + Star_using_triangles::const_iterator it_simplex = star_using_triangles.begin(); - Star_using_triangles::const_iterator it_simplex_end = + Star_using_triangles::const_iterator it_simplex_end = star_using_triangles.end(); for ( ; it_simplex != it_simplex_end ; ++it_simplex) { // Don't export infinite cells - if (*it_simplex->first.rbegin() + if (*it_simplex->first.rbegin() == std::numeric_limits::max()) continue; - + const std::set &c = it_simplex->first; int color_simplex = it_simplex->second; @@ -2858,7 +2858,7 @@ next_face: // Do not export smaller dimension simplices if (num_vertices < m_intrinsic_dimension + 1) continue; - + // If m_intrinsic_dimension = 1, each point is output two times, // so we need to multiply each index by 2 // And if only 2 vertices, add a third one (each vertex is duplicated in @@ -2888,13 +2888,13 @@ next_face: { std::set triangle; std::set::iterator it = c.begin(); - for (int i = 0; it != c.end() ; ++i, ++it) + for (int i = 0; it != c.end() ; ++i, ++it) { if (booleans[i]) triangle.insert(*it); } triangles.push_back(triangle); - } + } while (std::next_permutation(booleans.begin(), booleans.end())); } @@ -2906,7 +2906,7 @@ next_face: // Don't export infinite cells if (*it_tri->rbegin() == std::numeric_limits::max()) continue; - + os << 3 << " "; std::set::const_iterator it_point_idx = it_tri->begin(); for ( ; it_point_idx != it_tri->end() ; ++it_point_idx) @@ -2952,7 +2952,7 @@ private: const double m_half_sparsity; const double m_sq_half_sparsity; const int m_ambient_dim; - + Points m_points; #ifdef CGAL_TC_PERTURB_WEIGHT Weights_for_perturb m_weights; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 531f3318c1b..fa95f035a41 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -32,7 +32,7 @@ #include #include -#include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) +#include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) // choose exact integral type for QP solver @@ -49,7 +49,7 @@ namespace Tangential_complex_ { // Provides copy constructors to std::atomic so that // it can be used in a vector template - struct Atomic_wrapper + struct Atomic_wrapper : public std::atomic { typedef std::atomic Base; @@ -59,7 +59,7 @@ namespace Tangential_complex_ { Atomic_wrapper(const std::atomic &a) : Base(a.load()) {} Atomic_wrapper(const Atomic_wrapper &other) : Base(other.load()) {} - + Atomic_wrapper &operator=(const T &other) { Base::store(other); @@ -173,7 +173,7 @@ namespace Tangential_complex_ { return output_basis; } - + // CJTODO: use CGAL::Combination_enumerator (cf. Tangential_complex.h) // Compute all the k-combinations of elements // Output_iterator::value_type must be std::set > @@ -200,7 +200,7 @@ namespace Tangential_complex_ { // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template bool does_voronoi_face_and_alpha_tangent_subspace_intersect( Point_range const& all_points, @@ -218,7 +218,7 @@ namespace Tangential_complex_ { typedef typename K::FT FT; typedef typename K::Point_d Point; typedef typename K::Vector_d Vector; - + typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); @@ -229,9 +229,9 @@ namespace Tangential_complex_ { std::size_t card_Q = Q.size(); std::size_t card_OSB = orthogonal_subspace_basis.size(); std::size_t num_couples_among_P = card_P*(card_P-1)/2; - std::size_t num_equations = + std::size_t num_equations = 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; - + // Linear solver typedef CGAL::Quadratic_program Linear_program; typedef CGAL::Quadratic_program_solution LP_solution; @@ -266,7 +266,7 @@ namespace Tangential_complex_ { { Point const& pi = P[pi_pj[0]]; Point const& pj = P[pi_pj[1]]; - + for (int k = 0 ; k < ambient_dim ; ++k) { FT a = 2*(pi[k] + pj[k]); @@ -293,7 +293,7 @@ namespace Tangential_complex_ { for (int k = 0 ; k < ambient_dim ; ++k) lp.set_a(k, current_row, 2*(qi[k] - p0[k])); - lp.set_b(current_row, + lp.set_b(current_row, scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)) - p0_dot_p0); ++current_row; diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 6b0c8c89b4c..695d7a93e86 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -48,7 +48,7 @@ public: // 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, + Point_sparsifier(Point_container &points, FT sparsity = FT(0.05*0.05)) : m_points(points), m_sparsity(sparsity), m_points_ds(NULL) {} @@ -72,7 +72,7 @@ public: return true; } } - + return false; } @@ -141,14 +141,14 @@ sparsify_point_set( typedef typename Points_ds::INS_range INS_range; typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); - + #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif // Create the output container std::vector output; - + Points_ds points_ds(input_pts); std::vector dropped_points(input_pts.size(), false); @@ -162,7 +162,7 @@ sparsify_point_set( { if (dropped_points[pt_idx]) continue; - + output.push_back(*it_pt); INS_range ins_range = points_ds.query_incremental_ANN(*it_pt); @@ -183,7 +183,7 @@ sparsify_point_set( break; } } - + #ifdef CGAL_TC_PROFILING std::cerr << "Point set sparsified in " << t.elapsed() << " seconds." << std::endl; @@ -277,7 +277,7 @@ std::vector generate_points_on_moment_curve( if (sparsifier.try_to_insert_point(p)) ++i; #else - points.push_back(p); + points.push_back(p); ++i; #endif } @@ -467,7 +467,7 @@ 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; - + Point p = construct_point(k, x1, x2, x3, x4, x5); #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) From 213cd0071ae47a7930c1f08f6eb2d5ebacdba959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:20:46 +0200 Subject: [PATCH 259/487] Additional compilation fixes (cherry picked from commit 207f119ab0dcd35a203b4da2d66508ccad927d0c) --- .../include/CGAL/Tangential_complex.h | 15 ++++++++------- .../include/CGAL/Tangential_complex/utilities.h | 5 ++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c7ccdecb53d..7a8d4a20b72 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -38,9 +38,7 @@ #include #include -#ifdef CGAL_TC_PROFILING # include -#endif #include // CJTODO TEMP @@ -258,7 +256,7 @@ public: return m_ambient_dim; } - std::size_t number_of_vertices() + std::size_t number_of_vertices() const { return m_points.size(); } @@ -668,7 +666,7 @@ public: // CJTODO: parallel_for??? for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) { - bool inconsistencies_found; + bool inconsistencies_found = false; do { Star::const_iterator it_inc_simplex = m_stars[idx].begin(); @@ -1123,9 +1121,11 @@ private: { Tr_point c = power_center( boost::make_transform_iterator( - cell->vertices_begin(), vertex_handle_to_point), + cell->vertices_begin(), + vertex_handle_to_point), boost::make_transform_iterator( - cell->vertices_end(), vertex_handle_to_point)); + cell->vertices_end(), + vertex_handle_to_point)); FT sq_power_sphere_diam = 4*point_weight(c); @@ -2482,8 +2482,9 @@ next_face: //----------------------------------------------------------------------- FT min_a = std::numeric_limits::max(); - for (auto idx : inside_pt_indices) // CJTODO: C++11 + for (std::size_t i = 0 ; i < inside_pt_indices.size() ; ++i) { + std::size_t idx = inside_pt_indices[i]; const Point ti = compute_perturbed_point(idx); const Point &cp = k_drop_w(global_Cp); const Point &cq = k_drop_w(global_Cq); diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index fa95f035a41..b575f7ff6f1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -160,11 +160,10 @@ namespace Tangential_complex_ { { Vector u = *inb_it; - typename Basis::iterator outb_it = output_basis.begin(); for (int j = 0 ; j < i ; ++j) { - Vector const& ej = *outb_it; - Vector u_proj = scaled_vec(ej, inner_pdct(u, ej)); + Vector const& ej = input_basis[j]; + Vector u_proj = scaled_vec(ej, inner_pdct(u, ej) / inner_pdct(ej, ej)); u = diff_vec(u, u_proj); } From 2997d7464b72f8501f3b4682c244a14f35142f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:32:12 +0200 Subject: [PATCH 260/487] Adapt TC code to be compatible with the anisotropic mesh algorithms The main changes are : -Points always have a weight (defaulted to 0), but we keep using Points and Weights vectors rather than Weighted_points to ease the interface with ANN queries. -Tangent spaces know a point through which they go to allow them to not necessarily go through their corresponding m_points. -Tangent spaces and weights can be set externally (cherry picked from commit ce8c08a03263e9769c76851a9fc5f63f40f9ac97) --- .../include/CGAL/Tangential_complex.h | 264 +++++++++--------- .../CGAL/Tangential_complex/utilities.h | 99 ++++--- 2 files changed, 192 insertions(+), 171 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7a8d4a20b72..077de236f6e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -128,19 +128,17 @@ class Tangential_complex typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename Tr_traits::Vector_d Tr_vector; - typedef std::vector Tangent_space_basis; - typedef std::vector Orthogonal_space_basis; + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; typedef std::vector Points; - typedef std::vector Weights; - #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) typedef tbb::mutex Mutex_for_perturb; typedef Vector Translation_for_perturb; - typedef std::vector > Weights_for_perturb; + typedef std::vector > Weights; #else typedef Vector Translation_for_perturb; - typedef std::vector Weights_for_perturb; + typedef std::vector Weights; #endif typedef std::vector Translations_for_perturb; @@ -186,8 +184,10 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; +public: typedef typename std::vector TS_container; typedef typename std::vector OS_container; +private: typedef typename std::vector Tr_container; typedef typename std::vector Vectors; @@ -226,17 +226,23 @@ public: m_half_sparsity(0.5*sparsity), m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), m_ambient_dim(k.point_dimension_d_object()(*first)), - m_points(first, last) + m_points(first, last), + m_weights(m_points.size(), FT(0)) # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) # endif , m_points_ds(m_points) + , m_are_tangent_spaces_computed(m_points.size(), false) + , m_tangent_spaces(m_points.size(), Tangent_space_basis()) +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) +#endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) #endif - {} + { } /// Destructor ~Tangential_complex() @@ -261,6 +267,35 @@ public: return m_points.size(); } + void set_weights(std::vector const& weights) + { + m_weights = weights; + } + + void set_tangent_planes(const TS_container& tangent_spaces +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + , const OS_container& orthogonal_spaces +#endif + ) + { +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + std::cerr << "Cannot use CGAL_TC_PERTURB_TANGENT_SPACE and set " + << " tangent spaces manually at the same time" << std::endl; + std::exit(EXIT_FAILURE); +#endif + CGAL_assertion(m_points.size() == tangent_spaces.size() +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + && m_points.size() == orthogonal_spaces.size() +#endif + ); + m_tangent_spaces = tangent_spaces; +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_orth_spaces = orthogonal_spaces; +#endif + for(std::size_t i=0; i::value) { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), - Compute_tangent_triangulation(*this, - true) //tangent_spaces_are_already_computed + Compute_tangent_triangulation(*this) ); } // Sequential @@ -398,16 +423,13 @@ public: for (std::size_t i = 0 ; i < m_points.size() ; ++i) { #ifdef CGAL_ALPHA_TC - compute_alpha_tangent_triangulation(i, ALPHA, - true); // tangent_spaces_are_already_computed + compute_alpha_tangent_triangulation(i, ALPHA); #else - compute_tangent_triangulation(i, - true); // tangent_spaces_are_already_computed + compute_tangent_triangulation(i); #endif } } - #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex refreshed in " << t.elapsed() << " seconds." << std::endl; @@ -951,22 +973,18 @@ private: class Compute_tangent_triangulation { Tangential_complex & m_tc; - bool m_tangent_spaces_are_already_computed; public: // Constructor Compute_tangent_triangulation( - Tangential_complex &tc, bool tangent_spaces_are_already_computed = false) - : m_tc(tc), - m_tangent_spaces_are_already_computed(tangent_spaces_are_already_computed) - {} + Tangential_complex &tc) + : m_tc(tc) + { } // Constructor Compute_tangent_triangulation(const Compute_tangent_triangulation &ctt) - : m_tc(ctt.m_tc), - m_tangent_spaces_are_already_computed( - ctt.m_tangent_spaces_are_already_computed) - {} + : m_tc(ctt.m_tc) + { } // operator() void operator()( const tbb::blocked_range& r ) const @@ -974,20 +992,16 @@ private: for( size_t i = r.begin() ; i != r.end() ; ++i) { #ifdef CGAL_ALPHA_TC - m_tc.compute_alpha_tangent_triangulation( - i, ALPHA, m_tangent_spaces_are_already_computed); + m_tc.compute_alpha_tangent_triangulation(i, ALPHA); #else - m_tc.compute_tangent_triangulation( - i, m_tangent_spaces_are_already_computed); + m_tc.compute_tangent_triangulation(i); #endif } } }; #endif // CGAL_LINKED_WITH_TBB - void compute_tangent_triangulation( - std::size_t i, bool tangent_spaces_are_already_computed = false, - bool verbose = false) + void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) std::cerr << "** Computing tangent tri #" << i << " **" << std::endl; @@ -1012,23 +1026,28 @@ private: const Point center_pt = compute_perturbed_point(i); // Estimate the tangent space - if (!tangent_spaces_are_already_computed) + if (!m_are_tangent_spaces_computed[i]) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_tangent_spaces[i] = - compute_tangent_space(center_pt, true, &m_orth_spaces[i]); + compute_tangent_space(center_pt, i, true/*normalize*/, &m_orth_spaces[i]); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt); + m_tangent_spaces[i] = compute_tangent_space(center_pt, i); #endif } #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = - compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); + m_tangent_spaces[i] = compute_tangent_space(center_pt, i, + true /*normalize_basis*/, + &m_orth_spaces[i], + true /*perturb*/); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); + m_tangent_spaces[i] = compute_tangent_space(center_pt, i, + true /*normalize_basis*/, + NULL /*ortho basis*/, + true /*perturb*/); #endif m_perturb_tangent_space[i] = false; } @@ -1040,15 +1059,11 @@ private: //*************************************************** // Insert p - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(m_intrinsic_dimension, ORIGIN), -#ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[i] -#else - 0 -#endif - ); - center_vertex = local_tr.insert(wp); + const Weighted_point wp = compute_perturbed_weighted_point(i); + Tr_point proj_wp = project_point_and_compute_weight(wp, m_tangent_spaces[i], + local_tr_traits); + + center_vertex = local_tr.insert(proj_wp); center_vertex->data() = i; if (verbose) std::cerr << "* Inserted point #" << i << std::endl; @@ -1087,7 +1102,7 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, neighbor_weight, center_pt, m_tangent_spaces[i], + neighbor_pt, neighbor_weight, m_tangent_spaces[i], local_tr_traits); Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); @@ -1193,10 +1208,9 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } - - void compute_alpha_tangent_triangulation( - std::size_t i, FT alpha, bool tangent_spaces_are_already_computed = false, - bool verbose = false) +#ifdef CGAL_ALPHA_TC + void compute_alpha_tangent_triangulation(std::size_t i, FT alpha, + bool verbose = false) { if (verbose) std::cerr << "** Computing alpha tangent tri #" @@ -1228,24 +1242,16 @@ private: const Point ¢er_pt = m_points[i]; // Estimate the tangent space - if (!tangent_spaces_are_already_computed) + if (!m_are_tangent_spaces_computed[i]) { -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_tangent_spaces[i] = - compute_tangent_space(center_pt, true, &m_orth_spaces[i]); -#else - m_tangent_spaces[i] = compute_tangent_space(center_pt); -#endif + compute_tangent_space(center_pt, i, true /*normalize*/, &m_orth_spaces[i]); } #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_tangent_spaces[i] = - compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); -#else - m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); -#endif + compute_tangent_space(center_pt, i, true, &m_orth_spaces[i], true); m_perturb_tangent_space[i] = false; } #endif @@ -1262,14 +1268,8 @@ private: Amb_RT local_amb_tr(m_ambient_dim); // Insert p - Weighted_point wp = m_k.construct_weighted_point_d_object()( - center_pt, -#ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[i] -#else - 0 -#endif - ); + Weighted_point wp = m_k.construct_weighted_point_d_object()(center_pt, + m_weights[i]); Amb_RT_VH center_vertex = local_amb_tr.insert(wp); center_vertex->data() = i; if (verbose) @@ -1491,7 +1491,8 @@ next_face: #endif bool does_intersect = does_voronoi_face_and_alpha_tangent_subspace_intersect( - m_points, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); + m_points, m_weights, i, P, curr_neighbors, + m_orth_spaces[i], alpha, m_k); #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) ttt_intersect += 1000000*t_inters.elapsed(); #endif @@ -1534,9 +1535,11 @@ next_face: //std::ofstream off_stream_tr(sstr.str()); //CGAL::export_triangulation_to_off(off_stream_tr, local_amb_tr); } +#endif // CGAL_ALPHA_TC Tangent_space_basis compute_tangent_space( const Point &p + , const std::size_t i , bool normalize_basis = true , Orthogonal_space_basis *p_orth_space_basis = NULL #ifdef CGAL_TC_PERTURB_TANGENT_SPACE @@ -1593,9 +1596,10 @@ next_face: Eigen::MatrixXd cov = centered.adjoint() * centered; Eigen::SelfAdjointEigenSolver eig(cov); + Tangent_space_basis tsb(p); // p = compute_perturbed_point(i) here + // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues - Tangent_space_basis ts; for (int i = m_ambient_dim - 1 ; i >= m_ambient_dim - m_intrinsic_dimension ; --i) @@ -1605,11 +1609,11 @@ next_face: Vector v = constr_vec(m_ambient_dim, eig.eigenvectors().col(i).data(), eig.eigenvectors().col(i).data() + m_ambient_dim); - ts.push_back(normalize_vector(v, m_k)); + tsb.push_back(normalize_vector(v, m_k)); } else { - ts.push_back(constr_vec( + tsb.push_back(constr_vec( m_ambient_dim, eig.eigenvectors().col(i).data(), eig.eigenvectors().col(i).data() + m_ambient_dim)); @@ -1618,6 +1622,7 @@ next_face: if (p_orth_space_basis) { + p_orth_space_basis->origin() = p; for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; i >= 0 ; --i) @@ -1639,14 +1644,15 @@ next_face: } } + m_are_tangent_spaces_computed[i] = true; + //************************************************************************* //Vector n = m_k.point_to_vector_d_object()(p); //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; - return ts; - + return tsb; // CJTODO: this is only for a sphere in R^3 /*double tt1[3] = {-p[1] - p[2], p[0], p[0]}; @@ -1677,7 +1683,8 @@ next_face: //ts.reserve(m_intrinsic_dimension); //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); - //return compute_gram_schmidt_basis(ts, m_k); + //ts = compute_gram_schmidt_basis(ts, m_k); + //return ts; */ } @@ -1699,11 +1706,7 @@ next_face: #else p = m_points[pt_idx]; #endif -#ifdef CGAL_TC_PERTURB_WEIGHT w = m_weights[pt_idx]; -#else - w = 0; -#endif } Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) @@ -1717,16 +1720,12 @@ next_face: #else m_points[pt_idx], #endif -#ifdef CGAL_TC_PERTURB_WEIGHT m_weights[pt_idx]); -#else - 0); -#endif return wp; } - Point unproject_point(const Tr_point &p, const Point &origin, + Point unproject_point(const Tr_point &p, const Tangent_space_basis &tsb, const Tr_traits &tr_traits) { @@ -1737,21 +1736,18 @@ next_face: typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object(); - Point global_point = origin; + Point global_point = tsb.origin(); for (int i = 0 ; i < m_intrinsic_dimension ; ++i) - { - global_point = k_transl( - global_point, - k_scaled_vec(tsb[i], coord(p, i))); - } + global_point = k_transl(global_point, + k_scaled_vec(tsb[i], coord(p, i))); return global_point; } // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p - Tr_bare_point project_point(const Point &p, const Point &origin, - const Tangent_space_basis &ts) const + Tr_bare_point project_point(const Point &p, + const Tangent_space_basis &tsb) const { typename Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); @@ -1763,9 +1759,9 @@ next_face: coords.reserve(m_intrinsic_dimension); for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { - // Compute the inner product p * ts[i] - Vector v = diff_points(p, origin); - FT coord = inner_pdct(v, ts[i]); + // Local coords are given by the inner product with the vectors of tsb + Vector v = diff_points(p, tsb.origin()); + FT coord = inner_pdct(v, tsb[i]); coords.push_back(coord); } @@ -1774,21 +1770,21 @@ next_face: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p - Tr_point project_point_and_compute_weight( - const Weighted_point &wp, const Point &origin, const Tangent_space_basis &ts, - const Tr_traits &tr_traits) const + Tr_point project_point_and_compute_weight(const Weighted_point &wp, + const Tangent_space_basis &tsb, + const Tr_traits &tr_traits) const { typename Kernel::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object(); typename Kernel::Point_weight_d k_point_weight = m_k.point_weight_d_object(); return project_point_and_compute_weight( - k_drop_w(wp), k_point_weight(wp), origin, ts, tr_traits); + k_drop_w(wp), k_point_weight(wp), tsb, tr_traits); } - Tr_point project_point_and_compute_weight( - const Point &p, FT w, const Point &origin, const Tangent_space_basis &ts, - const Tr_traits &tr_traits) const + Tr_point project_point_and_compute_weight(const Point &p, const FT w, + const Tangent_space_basis &tsb, + const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); typename Kernel::Scalar_product_d inner_pdct = @@ -1798,21 +1794,21 @@ next_face: typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); - Vector v = diff_points(p, origin); + Vector v = diff_points(p, tsb.origin()); std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(ccci(origin), ccci(origin, 0)); + std::vector p_proj(ccci(tsb.origin()), ccci(tsb.origin(), 0)); coords.reserve(m_intrinsic_dimension); for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { - // Compute the inner product p * ts[i] - FT coord = inner_pdct(v, ts[i]); + // Local coords are given by the inner product with the vectors of tsb + FT coord = inner_pdct(v, tsb[i]); coords.push_back(coord); // p_proj += coord * v; for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += coord * ts[i][j]; + p_proj[j] += coord * tsb[i][j]; } Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); @@ -1903,7 +1899,7 @@ next_face: { // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); + m_weights[point_idx] += m_random_generator.get_double(0., m_sq_half_sparsity); #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE @@ -2105,15 +2101,9 @@ next_face: // space. Could be optimized since it's already been computed before. for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { -#ifdef CGAL_TC_PERTURB_WEIGHT - FT w = m_weights[*it_point_idx]; -#else - FT w = 0; -#endif simplex_pts.push_back(project_point_and_compute_weight( - m_points[*it_point_idx], w, - m_points[tr_index], m_tangent_spaces[tr_index], - local_tr_traits)); + m_points[*it_point_idx], m_weights[*it_point_idx], + m_tangent_spaces[tr_index], local_tr_traits)); } typename Tr_traits::Power_center_d power_center = @@ -2123,7 +2113,6 @@ next_face: Point global_center = unproject_point( power_center(simplex_pts.begin(), simplex_pts.end()), - m_points[tr_index], m_tangent_spaces[tr_index], local_tr_traits); @@ -2317,7 +2306,6 @@ next_face: // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions const Point pt_p = compute_perturbed_point(p_idx); - const Point pt_q = compute_perturbed_point(q_idx); std::set::const_iterator it_point_idx = inconsistent_simplex.begin(); @@ -2331,9 +2319,9 @@ next_face: // No need to lock the Mutex_for_perturb here since this will not be // called while other threads are perturbing the positions simplex_pts_in_Tp.push_back(project_point_and_compute_weight( - wp, pt_p, m_tangent_spaces[p_idx], q_tr_traits)); + wp, m_tangent_spaces[p_idx], q_tr_traits)); simplex_pts_in_Tq.push_back(project_point_and_compute_weight( - wp, pt_q, m_tangent_spaces[q_idx], q_tr_traits)); + wp, m_tangent_spaces[q_idx], q_tr_traits)); } Tr_point Cp = tr_power_center( @@ -2352,14 +2340,13 @@ next_face: #endif Weighted_point global_Cp = k_constr_wp( - unproject_point(Cp, pt_p, m_tangent_spaces[p_idx], q_tr_traits), + unproject_point(Cp, m_tangent_spaces[p_idx], q_tr_traits), circumsphere_sqradius_p); Weighted_point global_Cq = k_constr_wp( - unproject_point(Cq, pt_q, m_tangent_spaces[q_idx], q_tr_traits), + unproject_point(Cq, m_tangent_spaces[q_idx], q_tr_traits), circumsphere_sqradius_q); - // CJTODO TEMP ==================== /*{ INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(global_Cp)); @@ -2422,7 +2409,7 @@ next_face: Orientation o = orient(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); auto p = project_point_and_compute_weight( compute_perturbed_weighted_point(neighbor_point_idx), - pt_q, m_tangent_spaces[q_idx], q_tr_traits); + m_tangent_spaces[q_idx], q_tr_traits); auto sid = (o == NEGATIVE ? side(simplex_pts_in_Tq.rbegin(), simplex_pts_in_Tq.rend(), p) : side(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end(), p)); @@ -2446,7 +2433,7 @@ next_face: // CJTODO TEMP DEBUG /*if (inside_pt_indices.empty()) { - //compute_tangent_triangulation(q_idx, true, true); + //compute_tangent_triangulation(q_idx, true); std::cerr << "Error: inside_pt_indices.empty()\n"; std::cerr << "Stars:\n"; for (auto s : m_stars[q_idx]) @@ -2955,9 +2942,7 @@ private: const int m_ambient_dim; Points m_points; -#ifdef CGAL_TC_PERTURB_WEIGHT - Weights_for_perturb m_weights; -#endif + Weights m_weights; #ifdef CGAL_TC_PERTURB_POSITION Translations_for_perturb m_translations; # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) @@ -2969,6 +2954,7 @@ private: #endif Points_ds m_points_ds; + mutable std::vector m_are_tangent_spaces_computed; TS_container m_tangent_spaces; #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) OS_container m_orth_spaces; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index b575f7ff6f1..9c26b2c48e2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -137,22 +137,46 @@ namespace Tangential_complex_ { return v; } - template - std::vector - compute_gram_schmidt_basis( - std::vector const& input_basis, - K const& k) + template + struct Basis { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + typedef typename std::vector::const_iterator const_iterator; + + Point m_origin; //fixme should probably be (const?) ref ? + std::vector m_vectors; + + Point& origin() { return m_origin; } + const Point& origin() const { return m_origin; } + const_iterator begin() const { return m_vectors.begin(); } + const_iterator end() const { return m_vectors.end(); } + std::size_t size() const { return m_vectors.size(); } + + Vector& operator[](const std::size_t i) { return m_vectors[i]; } + const Vector& operator[](const std::size_t i) const { return m_vectors[i]; } + void push_back(const Vector& v) { m_vectors.push_back(v); } + void reserve(const std::size_t s) { m_vectors.reserve(s); } + + Basis() { } + Basis(const Point& p) : m_origin(p) { } + Basis(const Point& p, const std::vector& vectors) + : m_origin(p), m_vectors(vectors) + { } + }; + + template + Basis compute_gram_schmidt_basis(Basis const& input_basis, K const& k) + { + typedef Basis Basis; typedef typename K::Vector_d Vector; - typedef std::vector Basis; // Kernel functors - typename K::Squared_length_d sqlen = k.squared_length_d_object(); typename K::Scaled_vector_d scaled_vec = k.scaled_vector_d_object(); typename K::Scalar_product_d inner_pdct = k.scalar_product_d_object(); typename K::Difference_of_vectors_d diff_vec = k.difference_of_vectors_d_object(); - Basis output_basis; + Basis output_basis(input_basis.origin()); typename Basis::const_iterator inb_it = input_basis.begin(); typename Basis::const_iterator inb_it_end = input_basis.end(); @@ -199,16 +223,18 @@ namespace Tangential_complex_ { // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template + template bool does_voronoi_face_and_alpha_tangent_subspace_intersect( - Point_range const& all_points, - std::size_t center_pt_index, - Indexed_point_range const& P, - Indexed_point_range_2 const& Q, - Vector_range const& orthogonal_subspace_basis, - typename K::FT alpha, - K const& k) + Point_range const& all_points, + Weight_range const& all_weights, + std::size_t center_pt_index, + Indexed_point_range const& P, + Indexed_point_range_2 const& Q, + Basis const& orthogonal_subspace_basis, + typename K::FT alpha, + K const& k) { // Notations: // Fv: Voronoi k-face @@ -220,9 +246,10 @@ namespace Tangential_complex_ { typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); + typename K::Compute_coordinate_d coord = k.compute_coordinate_d_object(); Point const& center_pt = all_points[center_pt_index]; - const int ambient_dim = k.point_dimension_d_object()(center_pt); + int const ambient_dim = k.point_dimension_d_object()(center_pt); std::size_t card_P = P.size(); std::size_t card_Q = Q.size(); @@ -239,21 +266,24 @@ namespace Tangential_complex_ { int current_row = 0; //=========== First set of equations =========== - // For point pi in P - // 2(p0 - pi).x = p0^2 - pi^2 + // For points pi in P + // 2(p0 - pi).x = p0^2 - w0 - pi^2 + wi Point const& p0 = center_pt; + FT const w0 = all_weights[center_pt_index]; FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); + for (typename Indexed_point_range::const_iterator it_p = P.begin(), it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { Point const& pi = all_points[*it_p]; + FT const wi = all_weights[*it_p]; for (int k = 0 ; k < ambient_dim ; ++k) - lp.set_a(k, current_row, 2*(p0[k] - pi[k])); + lp.set_a(k, current_row, 2*(coord(p0, k) - coord(pi, k))); - lp.set_b(current_row, - p0_dot_p0 - scalar_pdct(pt_to_vec(pi), pt_to_vec(pi))); + FT pi_dot_pi = scalar_pdct(pt_to_vec(pi), pt_to_vec(pi)); + lp.set_b(current_row, p0_dot_p0 - pi_dot_pi - w0 + wi); lp.set_r(current_row, CGAL::EQUAL); ++current_row; @@ -264,16 +294,18 @@ namespace Tangential_complex_ { for ( ; !pi_pj.finished() ; ++pi_pj) { Point const& pi = P[pi_pj[0]]; + FT wi = all_weights[pi_pj[0]]; Point const& pj = P[pi_pj[1]]; + FT wj = all_weights[pi_pj[1]]; for (int k = 0 ; k < ambient_dim ; ++k) { - FT a = 2*(pi[k] + pj[k]); + FT a = 2*(coord(pi, k) + coord(pj, k)); lp.set_a(k, current_row , -a); lp.set_a(k, current_row + 1, a); } - FT b = scalar_pdct(pi, pi) - scalar_pdct(pj, pj); + FT b = scalar_pdct(pi, pi) - wi - scalar_pdct(pj, pj) + wj; lp.set_b(current_row , -b); lp.set_b(current_row + 1, b); @@ -282,27 +314,29 @@ namespace Tangential_complex_ { //=========== Second set of equations =========== // For each point qi in Q - // 2(qi - p0).x <= qi^2 - p0^2 + // 2(qi - p0).x <= qi^2 - wi - p0^2 + w0 for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), it_q_end = Q.end() ; it_q != it_q_end ; ++it_q) { Point const& qi = all_points[*it_q]; + FT const wi = all_weights[*it_q]; for (int k = 0 ; k < ambient_dim ; ++k) - lp.set_a(k, current_row, 2*(qi[k] - p0[k])); + lp.set_a(k, current_row, 2*(coord(qi, k) - coord(p0, k))); - lp.set_b(current_row, - scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)) - p0_dot_p0); + FT qi_dot_qi = scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)); + lp.set_b(current_row, qi_dot_qi - wi - p0_dot_p0 + w0); ++current_row; } //=========== Third set of equations =========== - // For each vector of OSB + // For each vector bi of OSB, (x-p).bi <= alpha and >= -alpha + // p is the origin of the basis // bi.x <= bi.p + alpha // -bi.x <= -bi.p + alpha - for (typename Vector_range::const_iterator it_osb = + for (typename Basis::const_iterator it_osb = orthogonal_subspace_basis.begin(), it_osb_end = orthogonal_subspace_basis.end() ; it_osb != it_osb_end ; ++it_osb) @@ -315,7 +349,8 @@ namespace Tangential_complex_ { lp.set_a(k, current_row + 1, -bi[k]); } - FT bi_dot_p = scalar_pdct(bi, pt_to_vec(center_pt)); + Point const& basis_origin = orthogonal_subspace_basis.origin(); + FT bi_dot_p = scalar_pdct(bi, pt_to_vec(basis_origin)); lp.set_b(current_row , bi_dot_p + alpha); lp.set_b(current_row + 1, -bi_dot_p + alpha); From 17739d847deebd839647fdaf9f76a7c2463f794d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:39:40 +0200 Subject: [PATCH 261/487] Clean code (trailing whitespace, indentation, etc.) (cherry picked from commit 75b44442cfbc4ba8b69160b98b8115ceda7d07ef) --- .../Tangential_complex/benchmark_tc.cpp | 36 ++++++++-------- .../include/CGAL/Tangential_complex.h | 42 +++++++------------ .../Tangential_complex/Simplicial_complex.h | 42 +++++++++---------- .../include/CGAL/Tangential_complex/config.h | 2 +- .../test_tangential_complex.cpp | 8 ++-- 5 files changed, 58 insertions(+), 72 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ca1513be303..548f0c48949 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -35,7 +35,7 @@ typedef CGAL::Epick_d Kernel; typedef Kernel::FT FT; typedef Kernel::Point_d Point; typedef CGAL::Tangential_complex< - Kernel, CGAL::Dynamic_dimension_tag, + Kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag> TC; class XML_perf_data @@ -248,18 +248,18 @@ void make_tc(std::vector &points, slash_index, input_name_stripped.find_last_of('.') - slash_index); int ambient_dim = k.point_dimension_d_object()(*points.begin()); - + #ifdef CGAL_TC_PROFILING Wall_clock_timer t_gen; #endif - + #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated in " << t_gen.elapsed() << " seconds." << std::endl; #endif - + CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); - + #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM std::vector points_not_sparse = points; #endif @@ -277,7 +277,7 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); - + //=========================================================================== // Compute Tangential Complex //=========================================================================== @@ -293,7 +293,7 @@ void make_tc(std::vector &points, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - + //=========================================================================== // CJTODO TEMP //=========================================================================== @@ -364,7 +364,7 @@ void make_tc(std::vector &points, best_num_inconsistent_local_tr); CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", final_num_inconsistent_local_tr); - + //========================================================================= // Export to OFF //========================================================================= @@ -379,7 +379,7 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", "N/A"); CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", "N/A"); } - + int max_dim = -1; double fix2_time = -1; double export_after_fix2_time = -1.; @@ -431,7 +431,7 @@ void make_tc(std::vector &points, //=========================================================================== if (collapse) complex.collapse(max_dim); - + //=========================================================================== // Is the result a pure pseudomanifold? //=========================================================================== @@ -480,8 +480,8 @@ void make_tc(std::vector &points, << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl << " * Export to OFF (before perturb): " << export_before_time << std::endl - << " * Fix inconsistencies 1: " << perturb_time - << " (" << num_perturb_steps << " steps) ==> " + << " * Fix inconsistencies 1: " << perturb_time + << " (" << num_perturb_steps << " steps) ==> " << (perturb_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl << " * Fix inconsistencies 2: " << fix2_time << std::endl << " * Export to OFF (after perturb): " << export_after_perturb_time << std::endl @@ -525,7 +525,7 @@ int main() int seed = CGAL::default_random.get_int(0, 1<<30); CGAL::default_random = CGAL::Random(); std::cerr << "Random seed = " << seed << std::endl; - + std::ifstream script_file; script_file.open(BENCHMARK_SCRIPT_FILENAME); // Script? @@ -619,13 +619,13 @@ int main() #endif std::cerr << std::endl << "TC #" << i << "..." << std::endl; - + std::vector points; if (input == "generate_moment_curve") { points = generate_points_on_moment_curve( - num_points, ambient_dim, + num_points, ambient_dim, std::atof(param1.c_str()), std::atof(param2.c_str())); } else if (input == "generate_plane") @@ -635,7 +635,7 @@ int main() else if (input == "generate_sphere_d") { points = generate_points_on_sphere_d( - num_points, ambient_dim, + num_points, ambient_dim, std::atof(param1.c_str()), std::atof(param2.c_str())); } @@ -665,12 +665,12 @@ int main() if (!points.empty()) { - make_tc(points, intrinsic_dim, sparsity, + make_tc(points, intrinsic_dim, sparsity, perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', time_limit_for_perturb, input.c_str()); std::cerr << "TC #" << i++ << " done." << std::endl; - std::cerr << std::endl << "---------------------------------" + std::cerr << std::endl << "---------------------------------" << std::endl << std::endl; } else diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 077de236f6e..dd9c1fe3f8e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -94,8 +94,8 @@ private: /// The class Tangential_complex represents a tangential complex template < - typename Kernel, - typename DimensionTag, + typename Kernel, // ambiant dimension + typename DimensionTag, // intrinsic dimension typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Regular_triangulation < @@ -209,7 +209,6 @@ private: } public: - typedef Tangential_complex_::Simplicial_complex Simplicial_complex; /// Constructor for a range of points @@ -366,10 +365,8 @@ public: for ( ; it_p != it_p_end ; ++it_p) { const Point &p = *it_p; - - KNS_range kns_range = m_points_ds.query_ANN( - p, NUM_POINTS_FOR_PCA, false); + KNS_range kns_range = m_points_ds.query_ANN(p, NUM_POINTS_FOR_PCA, false); //******************************* PCA ************************************* // One row = one point @@ -388,7 +385,6 @@ public: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues - Tangent_space_basis ts; for (int i = 0 ; i < m_ambient_dim ; ++i) sum_eigen_values[i] += eig.eigenvalues()[i]; @@ -449,9 +445,6 @@ public: Wall_clock_timer t; - typename Kernel::Point_drop_weight_d drop_w = - m_k.point_drop_weight_d_object(); - #ifdef CGAL_TC_VERBOSE std::cerr << "Fixing inconsistencies..." << std::endl; #endif @@ -590,7 +583,6 @@ public: return TC_FIXED; } - // Return a pair std::pair number_of_inconsistent_simplices( #ifdef CGAL_TC_VERBOSE @@ -607,9 +599,6 @@ public: // For each triangulation for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { - Triangulation const& tr = it_tr->tr(); - Tr_vertex_handle center_vh = it_tr->center_vertex(); - // For each cell Star::const_iterator it_inc_simplex = m_stars[idx].begin(); Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); @@ -660,8 +649,6 @@ public: // For each triangulation for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { - Triangulation const& tr = it_tr->tr(); - // For each cell of the star Star::const_iterator it_inc_simplex = m_stars[idx].begin(); Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); @@ -843,8 +830,7 @@ public: for (int dim = lowest_dim ; dim <= highest_dim ; ++dim) { - CGAL::Combination_enumerator combi( - dim + 1, 0, m_ambient_dim + 1); + CGAL::Combination_enumerator combi(dim + 1, 0, m_ambient_dim + 1); for ( ; !combi.finished() ; ++combi) { @@ -1401,7 +1387,7 @@ private: // Fill faces_and_neighbors // Let's first take care of the D-faces typename std::vector::const_iterator it_c = incident_cells.begin(); - typename std::vector::const_iterator it_c_end= incident_cells.end(); + typename std::vector::const_iterator it_c_end = incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { @@ -1694,7 +1680,7 @@ next_face: return m_k.translated_point_d_object()( m_points[pt_idx], m_translations[pt_idx]); #else - return m_points[pt_idx]; + return m_points[pt_idx]; #endif } @@ -1914,17 +1900,17 @@ next_face: CGAL::Random_points_on_sphere_d tr_point_on_sphere_generator(m_ambient_dim, 1); // Parallel -# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) - Vector transl = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), m_half_sparsity); +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + Vector transl = k_scaled_vec(k_pt_to_vec(*tr_point_on_sphere_generator++), + m_half_sparsity); m_p_perturb_mutexes[point_idx].lock(); m_translations[point_idx] = transl; m_p_perturb_mutexes[point_idx].unlock(); // Sequential -# else +# else m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( *tr_point_on_sphere_generator++), m_half_sparsity); -# endif +# endif # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL const Tr_traits &local_tr_traits = @@ -1954,14 +1940,14 @@ next_face: ); } // Parallel -# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) m_p_perturb_mutexes[point_idx].lock(); m_translations[point_idx] = global_transl; m_p_perturb_mutexes[point_idx].unlock(); // Sequential -# else +# else m_translations[point_idx] = global_transl; -# endif +# endif # endif // CGAL_TC_PERTURB_POSITION_TANGENTIAL #endif // CGAL_TC_PERTURB_POSITION diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index efd3e7646a0..73422444aa2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -119,7 +119,7 @@ public: #endif // We note k = max_simplex_dim - 1 int k = max_simplex_dim - 1; - + typedef Complex::iterator Simplex_iterator; typedef std::vector Simplex_iterator_list; typedef std::map Cofaces_map; @@ -127,9 +127,9 @@ public: // Create a map associating each non-maximal k-faces to the list of its // maximal cofaces Cofaces_map cofaces_map; - for (Complex::const_iterator it_simplex = m_complex.begin(), + for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; - it_simplex != it_simplex_end ; + it_simplex != it_simplex_end ; ++it_simplex) { if (it_simplex->size() > k + 1) @@ -157,7 +157,7 @@ public: if (it_map_elt->second.size() == 1) { std::vector k_faces; - const Simplex_iterator_list::value_type &it_Cf = + const Simplex_iterator_list::value_type &it_Cf = *it_map_elt->second.begin(); CGAL_assertion(it_Cf->size() == max_simplex_dim + 1); // Get the k-faces composing the simplex @@ -177,10 +177,10 @@ public: { Simplex_iterator_list::iterator it = std::find( it_comb_in_map->second.begin(), - it_comb_in_map->second.end(), + it_comb_in_map->second.end(), it_Cf); CGAL_assertion(it != it_comb_in_map->second.end()); - it_comb_in_map->second.erase(it); + it_comb_in_map->second.erase(it); } } } @@ -201,8 +201,8 @@ public: void display_stats() const { std::cerr << "==========================================================\n"; - std::cerr << "Complex stats:\n"; - + std::cerr << "Complex stats:\n"; + if (m_complex.empty()) { std::cerr << "No simplices.\n"; @@ -212,18 +212,18 @@ public: // Number of simplex for each dimension std::map simplex_stats; - for (Complex::const_iterator it_simplex = m_complex.begin(), + for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; - it_simplex != it_simplex_end ; + it_simplex != it_simplex_end ; ++it_simplex) { ++simplex_stats[static_cast(it_simplex->size()) - 1]; } - + for (std::map::const_iterator it_map = simplex_stats.begin() ; it_map != simplex_stats.end() ; ++it_map) { - std::cerr << " * " << it_map->first << "-simplices: " + std::cerr << " * " << it_map->first << "-simplices: " << it_map->second << std::endl; } } @@ -234,31 +234,31 @@ public: // verbose_level = 0, 1 or 2 bool is_pure_pseudomanifold__do_not_check_if_stars_are_connected( int simplex_dim, - bool exit_at_the_first_problem = false, + bool exit_at_the_first_problem = false, int verbose_level = 0, std::size_t *p_num_wrong_dim_simplices = NULL, std::size_t *p_num_wrong_number_of_cofaces = NULL) { typedef std::set K_1_face; typedef std::map Cofaces_map; - + std::size_t num_wrong_dim_simplices = 0; std::size_t num_wrong_number_of_cofaces = 0; // Counts the number of cofaces of each K_1_face - + // Create a map associating each non-maximal k-faces to the list of its // maximal cofaces Cofaces_map cofaces_map; - for (Complex::const_iterator it_simplex = m_complex.begin(), + for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; - it_simplex != it_simplex_end ; + it_simplex != it_simplex_end ; ++it_simplex) { if (it_simplex->size() != simplex_dim + 1) { if (verbose_level >= 2) - std::cerr << "Found a simplex with dim = " + std::cerr << "Found a simplex with dim = " << it_simplex->size() - 1 << std::endl; ++num_wrong_dim_simplices; } @@ -283,7 +283,7 @@ public: if (it_map_elt->second != 2) { if (verbose_level >= 2) - std::cerr << "Found a k-1-face with " + std::cerr << "Found a k-1-face with " << it_map_elt->second << " cofaces\n"; if (exit_at_the_first_problem) @@ -300,9 +300,9 @@ public: std::cerr << "is_pure_manifold: " << (ret ? "YES" : "NO") << std::endl; if (!ret) { - std::cerr << " * Number of wrong dimension simplices: " + std::cerr << " * Number of wrong dimension simplices: " << num_wrong_dim_simplices << std::endl - << " * Number of wrong number of cofaces: " + << " * Number of wrong number of cofaces: " << num_wrong_number_of_cofaces << std::endl; } } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 1ba33d4eead..9c53d41b69b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -23,7 +23,7 @@ #include -// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false +// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false // positives in Intel TBB // (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/) #ifdef _DEBUG diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index cc9536db937..691f5429c78 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -52,9 +52,9 @@ int main() typedef Kernel::FT FT; typedef Kernel::Point_d Point; typedef CGAL::Tangential_complex< - Kernel, CGAL::Dimension_tag, + Kernel, CGAL::Dimension_tag, CGAL::Parallel_tag> TC; - + int i = 0; bool stop = false; //for ( ; !stop ; ++i) @@ -149,8 +149,8 @@ int main() << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl << " * Export to OFF (before fix): " << export_before_time << std::endl - << " * Fix inconsistencies: " << fix_time - << " (" << num_fix_steps << " steps) ==> " + << " * Fix inconsistencies: " << fix_time + << " (" << num_fix_steps << " steps) ==> " << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl << " * Export to OFF (after fix): " << export_after_time << std::endl << "================================================" << std::endl From b4f28869cff635fa20906541693e37bffc5c4160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:40:53 +0200 Subject: [PATCH 262/487] Add an example of aniso meshing with /Tangential_complex (first draft, missing a couple functions) (cherry picked from commit a6fdf30f850fbbf8cf3a3c0da902bda258c4fb41) --- .../test/Tangential_complex/CMakeLists.txt | 2 + .../test/Tangential_complex/aniso_TC.cpp | 271 ++++++++++++++++++ 2 files changed, 273 insertions(+) create mode 100644 Tangential_complex/test/Tangential_complex/aniso_TC.cpp diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt index 230af037117..b0cf36ef8ee 100644 --- a/Tangential_complex/test/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -62,11 +62,13 @@ if ( CGAL_FOUND ) include( ${EIGEN3_USE_FILE} ) include_directories (BEFORE "../../include") include_directories (BEFORE "include") + include_directories(../../../Anisotropic_mesh_TC/include) set (SOURCE_FILES "test_tangential_complex.cpp") ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES) create_single_source_cgal_program( ${SOURCE_FILES} ) + create_single_source_cgal_program( "aniso_TC.cpp" ) create_single_source_cgal_program( "test_utilities.cpp" ) else() diff --git a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp new file mode 100644 index 00000000000..09534985fef --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp @@ -0,0 +1,271 @@ +#include +#include +#include +#include + +#include "../../test/Tangential_complex/test_utilities.h" + +#include // Anisotropic metrics + +#include +#include +#include + +const int k = 2; // intrinsic +const int d = 5; // ambiant + +typedef CGAL::Epick_d< CGAL::Dimension_tag > Kk; +typedef CGAL::Epick_d< CGAL::Dimension_tag > Kd; +typedef Kk::FT FT; +typedef Kk::Point_d Point_k; +typedef Kd::Point_d Point_d; +typedef Kd::Weighted_point_d Weighted_point_d; +typedef Kd::Vector_d Vector_d; +typedef CGAL::Tangential_complex, + CGAL::Parallel_tag> TC; + +typedef CGAL::Tangential_complex_::Basis Basis; +typedef CGAL::Anisotropic_mesh_TC::Metric_base Metric; +typedef CGAL::Anisotropic_mesh_TC::Metric_field Metric_field; + +typedef typename Metric::E_Matrix E_Matrix_k; +typedef typename Metric::E_Vector E_Vector_k; +typedef Eigen::Matrix E_Vector_d; +typedef Eigen::Matrix E_Matrix_dk; + +void read_points(std::vector& points, + const Kk kerk = Kk()) +{ + std::ifstream in("../../../../Anisotropic_mesh_2/examples/Anisotropic_mesh_2/bambimboum.mesh"); +// std::ifstream in("aniso_regular.mesh"); + std::string word; + int useless, nv, dd; + FT x; + + in >> word >> useless; //MeshVersionFormatted i + in >> word >> dd; //Dimension d + in >> word >> nv; + + assert(dd == Kk::Dimension::value); + + for(int i=0; i ids; + for(int j=0; j> x; + ids.push_back(x); + } + in >> useless; + points.push_back(kerk.construct_point_d_object()(ids.begin(), ids.begin() + k)); + + if(points.size() == 200) + break; + } + + std::cout << points.size() << " points" << std::endl; +} + +// compute the corresponding point on the paraboloid (these points will be the +// points at which we compute tangent planes) +Point_d to_Q(const Point_k& p) +{ + typename Kk::Compute_coordinate_d k_coord = Kk().compute_coordinate_d_object(); + + E_Vector_d p_on_Q; + for(int i=0; i const & points_k, + Metric_field const * const mf, + std::vector& points_d, + std::vector& weights, + Kd const kerd = Kd()) +{ + typename Kd::Point_drop_weight_d k_drop_w = kerd.point_drop_weight_d_object(); + typename Kd::Point_weight_d k_point_weight = kerd.point_weight_d_object(); + + for(std::size_t i=0; icompute_metric(p); + Weighted_point_d wp = to_S(p, met, kerd); + points_d.push_back(k_drop_w(wp)); + weights.push_back(k_point_weight(wp)); + } +} + +void compute_and_set_tangent_planes(TC& tc, + const std::vector& points_k, + Kd const kerd = Kd()) +{ + typedef TC::TS_container TS_container; + typedef TC::OS_container OS_container; + + typename Kd::Compute_coordinate_d coord = kerd.compute_coordinate_d_object(); + typename Kd::Construct_vector_d constr_vec = kerd.construct_vector_d_object(); + TS_container tsc; + OS_container osc; + std::size_t n = tc.number_of_vertices(); + CGAL_assertion(n == points_k.size()); + + for(std::size_t c=0; c& points_k, + Metric_field const * const mf) +{ + Kd ker_d; + + std::vector points_d; + std::vector weights; + compute_points_in_ambiant_space(points_k, mf, points_d, weights, ker_d); + + TC tc(points_d.begin(), points_d.end(), 0./*sparsity*/, k /*intr dim*/, ker_d); + tc.set_weights(weights); + compute_and_set_tangent_planes(tc, points_k, ker_d); + + tc.compute_tangential_complex(); + + TC::Simplicial_complex complex; + int max_dim = tc.export_TC(complex, false); + complex.display_stats(); + { + std::ofstream off_stream("aniso_alpha_complex.off"); + tc.export_to_off(complex, off_stream); + } + + // Collapse + complex.collapse(max_dim); + { + std::ofstream off_stream("aniso_after_collapse.off"); + tc.export_to_off(complex, off_stream); + } + + std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces; + bool pure_manifold = complex.is_pure_manifold(k, false, 1, + &num_wrong_dim_simplices, + &num_wrong_number_of_cofaces); + complex.display_stats(); + + translate_connectivity_to_original_point_set(); + return; +} + +int main() +{ + CGAL::default_random = CGAL::Random(); + std::vector points_k; + + Metric_field* mf = NULL; + + read_points(points_k); + make_tc(points_k, mf); + + return 0; +} From 83e01e3a910c0942f2378ab8d56b8f4c41e03bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:57:40 +0200 Subject: [PATCH 263/487] Add a tiny comment (cherry picked from commit 5a3b3edd6a6cbab4f5d56b08474ef8f4b4cbab7b) --- Tangential_complex/include/CGAL/Tangential_complex.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index dd9c1fe3f8e..f561db9e546 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1283,6 +1283,12 @@ private: // called while other threads are perturbing the positions Weighted_point neighbor_wp = compute_perturbed_weighted_point(neighbor_point_idx); +// fixme ? +// Above seems incorrect since we later pass m_points[] to +// "does_voronoi_face_and_alpha_tangent_subspace_intersect()" and we lose +// the possible position pertubation of wp. +// Either we ignore the translations and it's neighbor_wp = points[idx]+weight +// or need to give m_translations to the voronoi intersections computations // "4*m_sq_half_sparsity" because both points can be perturbed if (squared_star_sphere_radius_plus_margin From ff00de4e22015c455d925fefa97b6a43e67a46f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 27 Apr 2015 14:28:29 +0200 Subject: [PATCH 264/487] Fix const correctness (cherry picked from commit 6b52e73a677f322bf3a2f17ec9eee7106b44d924) --- .../include/CGAL/Tangential_complex.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f561db9e546..3568ca7e5a4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -351,7 +351,7 @@ public: #endif } - void estimate_intrinsic_dimension() + void estimate_intrinsic_dimension() const { // Kernel functors typename Kernel::Compute_coordinate_d coord = @@ -590,7 +590,7 @@ public: #else bool verbose = false #endif - ) + ) const { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; @@ -787,7 +787,7 @@ public: bool check_if_all_simplices_are_in_the_ambient_delaunay( const Simplicial_complex *p_complex = NULL, bool check_for_any_dimension_simplices = true, - std::set > * incorrect_simplices = NULL) + std::set > * incorrect_simplices = NULL) const { typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; @@ -1537,7 +1537,7 @@ next_face: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE , bool perturb = false #endif - ) const + ) { //******************************* PCA ************************************* @@ -1690,7 +1690,7 @@ next_face: #endif } - void compute_perturbed_weighted_point(std::size_t pt_idx, Point &p, FT &w) + void compute_perturbed_weighted_point(std::size_t pt_idx, Point &p, FT &w) const { #ifdef CGAL_TC_PERTURB_POSITION p = m_k.translated_point_d_object()( @@ -1701,7 +1701,7 @@ next_face: w = m_weights[pt_idx]; } - Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) + Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) const { typename Kernel::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); @@ -1719,7 +1719,7 @@ next_face: Point unproject_point(const Tr_point &p, const Tangent_space_basis &tsb, - const Tr_traits &tr_traits) + const Tr_traits &tr_traits) const { typename Kernel::Translated_point_d k_transl = m_k.translated_point_d_object(); @@ -2781,6 +2781,7 @@ next_face: return os; } +public: std::ostream &export_simplices_to_off( const Simplicial_complex &complex, std::ostream & os, std::size_t &num_simplices, @@ -2946,7 +2947,7 @@ private: #endif Points_ds m_points_ds; - mutable std::vector m_are_tangent_spaces_computed; + std::vector m_are_tangent_spaces_computed; TS_container m_tangent_spaces; #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) OS_container m_orth_spaces; From 3a2a4f1863c84c5b381b25111b3026b814d0e970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 27 Apr 2015 18:55:54 +0200 Subject: [PATCH 265/487] Added the necessary functions for aniso using /Tangential_complex Non-alpha version for now. /Anisotropic_mesh_TC and aniso using /Tangential_complex give the same results (which is a good thing). (cherry picked from commit 1fe5556389966b912234dafe2be54502d6398c34) --- .../test/Tangential_complex/aniso_TC.cpp | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp index 09534985fef..586c63b0bdc 100644 --- a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp +++ b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp @@ -6,6 +6,8 @@ #include "../../test/Tangential_complex/test_utilities.h" #include // Anisotropic metrics +#include +#include #include #include @@ -34,6 +36,9 @@ typedef typename Metric::E_Vector E_Vector_k; typedef Eigen::Matrix E_Vector_d; typedef Eigen::Matrix E_Matrix_dk; +typedef CGAL::Anisotropic_mesh_TC::Euclidean_metric_field Euclidean_mf; +typedef CGAL::Anisotropic_mesh_TC::Custom_metric_field Custom_mf; + void read_points(std::vector& points, const Kk kerk = Kk()) { @@ -169,12 +174,13 @@ void compute_and_set_tangent_planes(TC& tc, E_Matrix_dk ts_m = E_Matrix_dk::Zero(); // 'first' part: x y z etc. derivates for(int i=0; i& points_k) { + std::ofstream out("aniso.off"); + std::stringstream output; + std::size_t num_simplices; + typename Kk::Compute_coordinate_d k_coord = Kk().compute_coordinate_d_object(); + + + for(std::size_t i=0; i& points_k, @@ -253,7 +278,7 @@ void make_tc(std::vector& points_k, &num_wrong_number_of_cofaces); complex.display_stats(); - translate_connectivity_to_original_point_set(); + export_complex_in_origin_space(tc, complex, points_k); return; } @@ -262,7 +287,8 @@ int main() CGAL::default_random = CGAL::Random(); std::vector points_k; - Metric_field* mf = NULL; + //Custom_mf* mf = new Custom_mf(); + Euclidean_mf* mf = new Euclidean_mf(); read_points(points_k); make_tc(points_k, mf); From 05500a49e02969889a6995c85db741668236d93f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 28 Apr 2015 11:52:53 +0200 Subject: [PATCH 266/487] Add point weights memory This is done to prevent consecutive weight perturbations from accumulating (cherry picked from commit 6f23a80ae682d515b301e0ac6c7f068005e18a64) --- .../include/CGAL/Tangential_complex.h | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3568ca7e5a4..652777aeb66 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -136,9 +136,15 @@ class Tangential_complex typedef tbb::mutex Mutex_for_perturb; typedef Vector Translation_for_perturb; typedef std::vector > Weights; + #ifdef CGAL_TC_PERTURB_WEIGHT + typedef std::vector > Weights_memory; + #endif #else typedef Vector Translation_for_perturb; typedef std::vector Weights; + #ifdef CGAL_TC_PERTURB_WEIGHT + typedef std::vector Weights_memory; + #endif #endif typedef std::vector Translations_for_perturb; @@ -227,6 +233,9 @@ public: m_ambient_dim(k.point_dimension_d_object()(*first)), m_points(first, last), m_weights(m_points.size(), FT(0)) +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights_memory(m_points.size(), FT(0)) +#endif # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) @@ -266,9 +275,12 @@ public: return m_points.size(); } - void set_weights(std::vector const& weights) + void set_weights(const Weights& weights) { m_weights = weights; +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights_memory = weights; +#endif } void set_tangent_planes(const TS_container& tangent_spaces @@ -1891,7 +1903,8 @@ next_face: { // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] += m_random_generator.get_double(0., m_sq_half_sparsity); + m_weights[point_idx] = m_weights_memory[point_idx] + + m_random_generator.get_double(0., m_sq_half_sparsity); #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE @@ -2936,6 +2949,9 @@ private: Points m_points; Weights m_weights; +#ifdef CGAL_TC_PERTURB_WEIGHT + Weights_memory m_weights_memory; +#endif #ifdef CGAL_TC_PERTURB_POSITION Translations_for_perturb m_translations; # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) From 9cfc9ea8ea4b9b56a303a1652af3ce0144489f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 28 Apr 2015 16:31:06 +0200 Subject: [PATCH 267/487] Avoid an unecessary initialization If external weights aren't set, the memory vector of weights will be full of 0 and isn't needed. (cherry picked from commit f6a4ba6169d792bf73a9121a7102d11a53469e24) --- Tangential_complex/include/CGAL/Tangential_complex.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 652777aeb66..5aee87487f8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -234,7 +234,7 @@ public: m_points(first, last), m_weights(m_points.size(), FT(0)) #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights_memory(m_points.size(), FT(0)) + m_weights_memory() #endif # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) @@ -1903,8 +1903,9 @@ next_face: { // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] = m_weights_memory[point_idx] + - m_random_generator.get_double(0., m_sq_half_sparsity); + m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); + if(m_weights_memory.size() > 0) // external weights were initially set + m_weights[point_idx] += m_weights_memory[point_idx] #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE From 7ff3c99876fc6eb00a4ea1eb5e189a4379eeae3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 28 Apr 2015 18:59:25 +0200 Subject: [PATCH 268/487] Avoid an unnecessary projection on tangent planes If the center of the star is the origin of the tangent basis, there is no need to compute a projection (it'll be the origin, locally) (cherry picked from commit e04c440477a43498aa79fa10e36f07893bcf572b) --- .../include/CGAL/Tangential_complex.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5aee87487f8..e035aa7c77c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1057,9 +1057,21 @@ private: //*************************************************** // Insert p - const Weighted_point wp = compute_perturbed_weighted_point(i); - Tr_point proj_wp = project_point_and_compute_weight(wp, m_tangent_spaces[i], - local_tr_traits); + typename Kernel::Equal_d eq = m_k.equal_d_object(); + + Tr_point proj_wp; + if(eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) + { + proj_wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(m_intrinsic_dimension, ORIGIN), + m_weights[i]); + } + else + { + const Weighted_point& wp = compute_perturbed_weighted_point(i); + proj_wp = project_point_and_compute_weight(wp, m_tangent_spaces[i], + local_tr_traits); + } center_vertex = local_tr.insert(proj_wp); center_vertex->data() = i; From e5407e014243b983e6c2d7532b9d7df8a5e8b282 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 17:39:09 +0200 Subject: [PATCH 269/487] Solve ambiguity on "i" --- .../include/CGAL/Tangential_complex.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index e035aa7c77c..38e7d1aa53f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1639,23 +1639,23 @@ next_face: if (p_orth_space_basis) { p_orth_space_basis->origin() = p; - for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; - i >= 0 ; - --i) + for (int j = m_ambient_dim - m_intrinsic_dimension - 1 ; + j >= 0 ; + --j) { if (normalize_basis) { Vector v = constr_vec(m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim); + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); p_orth_space_basis->push_back(normalize_vector(v, m_k)); } else { p_orth_space_basis->push_back(constr_vec( m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim)); + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); } } } From 3ceb5992b07fabf29a4ae0437624851cb81fe18e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 17:55:06 +0200 Subject: [PATCH 270/487] fix_inconsistencies => fix_inconsistencies_using_perturbation --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 2 +- Tangential_complex/include/CGAL/Tangential_complex.h | 8 ++++---- .../test/Tangential_complex/test_tangential_complex.cpp | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 548f0c48949..9cf7efbb3e4 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -352,7 +352,7 @@ void make_tc(std::vector &points, std::size_t initial_num_inconsistent_local_tr; std::size_t best_num_inconsistent_local_tr; std::size_t final_num_inconsistent_local_tr; - perturb_ret = tc.fix_inconsistencies( + perturb_ret = tc.fix_inconsistencies_using_perturbation( num_perturb_steps, initial_num_inconsistent_local_tr, best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, time_limit_for_perturb); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 38e7d1aa53f..d484bc65b94 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -445,7 +445,7 @@ public: } // time_limit in seconds: 0 = no fix to do, < 0 = no time limit - Fix_inconsistencies_status fix_inconsistencies( + Fix_inconsistencies_status fix_inconsistencies_using_perturbation( unsigned int &num_steps, std::size_t &initial_num_inconsistent_local_tr, std::size_t &best_num_inconsistent_local_tr, @@ -533,7 +533,7 @@ public: << "Inconsistencies (detailed stats):\n" << " * Number of vertices: " << m_points.size() << std::endl << std::endl - << " * BEFORE fix_inconsistencies:" << std::endl + << " * BEFORE fix_inconsistencies_using_perturbation:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_before.first << std::endl << " - Num inconsistent simplices in stars (incl. duplicates): " @@ -545,7 +545,7 @@ public: << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl << std::endl - << " * AFTER fix_inconsistencies:" << std::endl + << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_after.first << std::endl << " - Num inconsistent simplices in stars (incl. duplicates): " @@ -563,7 +563,7 @@ public: std::cerr << std::endl << "==========================================================" << std::endl - << "fix_inconsistencies():\n" + << "fix_inconsistencies_using_perturbation():\n" << " * " << m_points.size() << " vertices" << std::endl << " * " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 691f5429c78..9ac1d555c5c 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -120,9 +120,10 @@ int main() std::size_t initial_num_inconsistent_local_tr; std::size_t best_num_inconsistent_local_tr; std::size_t final_num_inconsistent_local_tr; - CGAL::Fix_inconsistencies_status fix_ret = tc.fix_inconsistencies( - num_fix_steps, initial_num_inconsistent_local_tr, - best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, 1000.); + CGAL::Fix_inconsistencies_status fix_ret = + tc.fix_inconsistencies_using_perturbation( + num_fix_steps, initial_num_inconsistent_local_tr, + best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, 1000.); double fix_time = t.elapsed(); t.reset(); double export_after_time = -1.; From 065d3554421005468410b3fbcd0d51d9c667f7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 20 Mar 2015 12:15:50 +0100 Subject: [PATCH 271/487] Fix compilation issues (cherry picked from commit 444c982540a1b4301d829556027784d81ffe0f55) Conflicts: Tangential_complex/include/CGAL/Tangential_complex.h --- Tangential_complex/include/CGAL/Tangential_complex.h | 4 ++-- .../include/CGAL/Tangential_complex/utilities.h | 2 +- Tangential_complex/test/Tangential_complex/test_utilities.h | 2 ++ Triangulation/include/CGAL/Triangulation_data_structure.h | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d484bc65b94..ae757607225 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -371,8 +371,8 @@ public: std::vector sum_eigen_values(m_ambient_dim, FT(0)); - Points::const_iterator it_p = m_points.begin(); - Points::const_iterator it_p_end = m_points.end(); + typename Points::const_iterator it_p = m_points.begin(); + typename Points::const_iterator it_p_end = m_points.end(); // For each point p for ( ; it_p != it_p_end ; ++it_p) { diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 9c26b2c48e2..b547125a1ef 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -210,7 +210,7 @@ namespace Tangential_complex_ { do { std::set combination; - Elements_container::const_iterator it_elt = elements.begin(); + typename Elements_container::const_iterator it_elt = elements.begin(); for (std::size_t i = 0 ; i < n ; ++i, ++it_elt) { if (booleans[i]) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 695d7a93e86..354e7bf5f2a 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -33,6 +33,8 @@ #include #include +#include + // 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 diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index ef10428a5c3..895a6f11b51 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -611,7 +611,8 @@ public: return incident_faces(v, dim, out, cmp, true); } template< typename OutputIterator, typename Comparator = std::less > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); + OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, + Comparator = Comparator(), bool = false) const; #else template< typename OutputIterator, typename Comparator > OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator()) From d0fe1db9dbdc28d090f22c49e07aee1b778ce02b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 6 May 2015 19:13:11 +0200 Subject: [PATCH 272/487] Added generators for tori --- .../test/Tangential_complex/test_utilities.h | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 354e7bf5f2a..4847a55c8bc 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -131,6 +131,18 @@ typename Kernel::Point_d construct_point( return k.construct_point_d_object()(5, &tab[0], &tab[5]); } +// construct_point: dim 6 +template +typename Kernel::Point_d construct_point( + const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3, + typename Kernel::FT x4, typename Kernel::FT x5, typename Kernel::FT x6) +{ + typename Kernel::FT tab[6]; + tab[0] = x1; tab[1] = x2; tab[2] = x3; tab[3] = x4; tab[4] = x5; tab[5] = x6; + return k.construct_point_d_object()(6, &tab[0], &tab[6]); +} + template std::vector sparsify_point_set( @@ -286,6 +298,128 @@ std::vector generate_points_on_moment_curve( return points; } + +// R = big radius, r = small radius +template +std::vector generate_points_on_torus_3D( + std::size_t num_points, double R, double r, bool uniform = false) +{ + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + + // if uniform + std::size_t num_lines = (std::size_t)sqrt(num_points); + std::size_t num_cols = num_points/num_lines + 1; + + std::vector points; + points.reserve(num_points); +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + FT u, v; + if (uniform) + { + std::size_t k1 = i / num_lines; + std::size_t k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } + else + { + u = rng.get_double(0, 6.2832); + v = rng.get_double(0, 6.2832); + } + double tmp = cos(u/2)*sin(v) - sin(u/2)*sin(2.*v); + Point p = construct_point(k, + (R + r * std::cos(u)) * std::cos(v), + (R + r * std::cos(u)) * std::sin(v), + r * std::sin(u)); +#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; +} + +template +static void generate_uniform_points_on_torus_d( + const Kernel &k, int dim, std::size_t num_slices, OutputIterator out, + std::vector current_point = std::vector()) +{ + if (current_point.size() == 2*dim) + { + *out++ = k.construct_point_d_object()( + current_point.size(), current_point.begin(), current_point.end()); + } + else + { + for (std::size_t slice_idx = 0 ; slice_idx < num_slices ; ++slice_idx) + { + std::vector cp2 = current_point; + FT alpha = 6.2832 * slice_idx / num_slices; + cp2.push_back(std::cos(alpha)); + cp2.push_back(std::sin(alpha)); + generate_uniform_points_on_torus_d( + k, dim, num_slices, out, cp2); + } + } +} + +template +std::vector generate_points_on_torus_d( + std::size_t num_points, int dim, bool uniform = false) +{ + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + + // if uniform + std::size_t num_slices = (std::size_t)std::pow(num_points, 1./dim); + + std::vector points; + points.reserve(num_points); + if (uniform) + { + generate_uniform_points_on_torus_d( + k, dim, num_slices, std::back_inserter(points)); + } + else + { +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + std::vector pt; + for (int curdim = 0 ; curdim < dim ; ++curdim) + { + FT alpha = rng.get_double(0, 6.2832); + pt.push_back(std::cos(alpha)); + pt.push_back(std::sin(alpha)); + } + + Point p = k.construct_point_d_object()(pt.size(), pt.begin(), pt.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; +} + template std::vector generate_points_on_sphere_d( std::size_t num_points, int dim, double radius, From 8fb2b9266345b1e584896baaba31faaf769e7668 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:44:14 +0200 Subject: [PATCH 273/487] Fix compilation + code clean-up --- .../include/CGAL/Tangential_complex.h | 103 ++++++++++++------ 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ae757607225..0c7457c7d7a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -65,13 +65,17 @@ #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) -#define CGAL_ALPHA_TC +//#define CGAL_ALPHA_TC const double ALPHA = 0.3; #ifdef CGAL_LINKED_WITH_TBB tbb::atomic ttt_star; // CJTODO TEMP tbb::atomic ttt_intersect; #endif +//CJTODO: debug +//#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 +//#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D + namespace CGAL { using namespace Tangential_complex_; @@ -234,12 +238,12 @@ public: m_points(first, last), m_weights(m_points.size(), FT(0)) #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights_memory() + , m_weights_memory() #endif -# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) -# endif +#endif , m_points_ds(m_points) , m_are_tangent_spaces_computed(m_points.size(), false) , m_tangent_spaces(m_points.size(), Tangent_space_basis()) @@ -294,11 +298,12 @@ public: << " tangent spaces manually at the same time" << std::endl; std::exit(EXIT_FAILURE); #endif - CGAL_assertion(m_points.size() == tangent_spaces.size() #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - && m_points.size() == orthogonal_spaces.size() + CGAL_assertion(m_points.size() == tangent_spaces.size() + && m_points.size() == orthogonal_spaces.size()); +#else + CGAL_assertion(m_points.size() == tangent_spaces.size()); #endif - ); m_tangent_spaces = tangent_spaces; #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_orth_spaces = orthogonal_spaces; @@ -540,7 +545,7 @@ public: << stats_before.second << " (" << 100. * stats_before.second / stats_before.first << "%)" << std::endl - << " * Num inconsistent local triangulations: " + << " * Num inconsistent stars: " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl @@ -567,7 +572,7 @@ public: << " * " << m_points.size() << " vertices" << std::endl << " * " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" - << " inconsistent triangulations encountered" << std::endl + << " inconsistent stars encountered" << std::endl << "==========================================================" << std::endl; # endif @@ -1563,7 +1568,50 @@ next_face: #endif ) { +#ifdef CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 + + // CJTODO: this is only for a sphere in R^3 + double tt1[3] = {-p[1] - p[2], p[0], p[0]}; + double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], + p[2] * tt1[0] - p[0] * tt1[2], + p[0] * tt1[1] - p[1] * tt1[0]}; + Vector t1(3, &tt1[0], &tt1[3]); + Vector t2(3, &tt2[0], &tt2[3]); + + // Normalize t1 and t2 + typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + + Tangent_space_basis ts; + ts.reserve(m_intrinsic_dimension); + ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); + ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); + + m_are_tangent_spaces_computed[i] = true; + + return ts; + +#elif defined(CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D) + + // CJTODO: this is only for torus_d + Tangent_space_basis ts(p); + ts.reserve(m_intrinsic_dimension); + for (int dim = 0 ; dim < m_intrinsic_dimension ; ++dim) + { + std::vector tt(m_ambient_dim, 0.); + tt[2*dim] = -p[2*dim + 1]; + tt[2*dim + 1] = p[2*dim]; + Vector t(2*m_intrinsic_dimension, tt.begin(), tt.end()); + ts.push_back(t); + } + + m_are_tangent_spaces_computed[i] = true; + + //return compute_gram_schmidt_basis(ts, m_k); + return ts; //******************************* PCA ************************************* + +#else // Kernel functors typename Kernel::Construct_vector_d constr_vec = @@ -1616,23 +1664,23 @@ next_face: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues - for (int i = m_ambient_dim - 1 ; - i >= m_ambient_dim - m_intrinsic_dimension ; - --i) + for (int j = m_ambient_dim - 1 ; + j >= m_ambient_dim - m_intrinsic_dimension ; + --j) { if (normalize_basis) { Vector v = constr_vec(m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim); + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); tsb.push_back(normalize_vector(v, m_k)); } else { tsb.push_back(constr_vec( m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim)); + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); } } @@ -1669,25 +1717,8 @@ next_face: //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; return tsb; - - // CJTODO: this is only for a sphere in R^3 - /*double tt1[3] = {-p[1] - p[2], p[0], p[0]}; - double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], - p[2] * tt1[0] - p[0] * tt1[2], - p[0] * tt1[1] - p[1] * tt1[0]}; - Vector t1(3, &tt1[0], &tt1[3]); - Vector t2(3, &tt2[0], &tt2[3]); - - // Normalize t1 and t2 - typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - - Tangent_space_basis ts; - ts.reserve(m_intrinsic_dimension); - ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); - ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); - - return ts;*/ + +#endif /* // Alternative code (to be used later) @@ -1917,7 +1948,7 @@ next_face: #ifdef CGAL_TC_PERTURB_WEIGHT m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); if(m_weights_memory.size() > 0) // external weights were initially set - m_weights[point_idx] += m_weights_memory[point_idx] + m_weights[point_idx] = m_weights[point_idx] + m_weights_memory[point_idx]; #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE From 9b0fca5019b5e3bdcc942bbce49d0e31fbce80f7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:46:40 +0200 Subject: [PATCH 274/487] Replaced NUM_POINTS_FOR_PCA by BASE_VALUE_FOR_PCA^intrinsic_dim --- .../include/CGAL/Tangential_complex.h | 21 ++++++++++++------- .../include/CGAL/Tangential_complex/config.h | 4 +++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 0c7457c7d7a..87278749384 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -375,6 +375,8 @@ public: m_k.compute_coordinate_d_object(); std::vector sum_eigen_values(m_ambient_dim, FT(0)); + std::size_t num_points_for_pca = + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dimension); typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -383,14 +385,14 @@ public: { const Point &p = *it_p; - KNS_range kns_range = m_points_ds.query_ANN(p, NUM_POINTS_FOR_PCA, false); + KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); //******************************* PCA ************************************* // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambient_dim); + Eigen::MatrixXd mat_points(num_points_for_pca, m_ambient_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; - j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + j < num_points_for_pca && nn_it != kns_range.end() ; ++j, ++nn_it) { for (int i = 0 ; i < m_ambient_dim ; ++i) @@ -1613,6 +1615,9 @@ next_face: #else + unsigned int num_points_for_pca = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dimension)); + // Kernel functors typename Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); @@ -1631,18 +1636,18 @@ next_face: #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM KNS_range kns_range = m_points_ds_for_tse.query_ANN( - p, NUM_POINTS_FOR_PCA, false); + p, num_points_for_pca, false); const Points &points_for_pca = m_points_for_tse; #else - KNS_range kns_range = m_points_ds.query_ANN(p, NUM_POINTS_FOR_PCA, false); + KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); const Points &points_for_pca = m_points; #endif // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambient_dim); + Eigen::MatrixXd mat_points(num_points_for_pca, m_ambient_dim); KNS_iterator nn_it = kns_range.begin(); - for (int j = 0 ; - j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + for (unsigned int j = 0 ; + j < num_points_for_pca && nn_it != kns_range.end() ; ++j, ++nn_it) { for (int i = 0 ; i < m_ambient_dim ; ++i) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 9c53d41b69b..060b1b75feb 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -65,6 +65,8 @@ //#define CGAL_TC_PERTURB_TANGENT_SPACE //========================= Parameters ======================================== -const std::size_t NUM_POINTS_FOR_PCA = 20; + +// PCA will use BASE_VALUE_FOR_PCA^intrinsic_dim points +const std::size_t BASE_VALUE_FOR_PCA = 5; #endif // CGAL_TC_CONFIG_H From fb0e11a2aa8e944c4d33894da9819523f9a79391 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:47:34 +0200 Subject: [PATCH 275/487] Fix collapse --- .../Tangential_complex/Simplicial_complex.h | 115 ++++++++++-------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 73422444aa2..ecdea36ce3a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -124,69 +124,76 @@ public: typedef std::vector Simplex_iterator_list; typedef std::map Cofaces_map; - // Create a map associating each non-maximal k-faces to the list of its - // maximal cofaces - Cofaces_map cofaces_map; - for (Complex::const_iterator it_simplex = m_complex.begin(), - it_simplex_end = m_complex.end() ; - it_simplex != it_simplex_end ; - ++it_simplex) + std::size_t num_collapsed_maximal_simplices = 0; + do { - if (it_simplex->size() > k + 1) + num_collapsed_maximal_simplices = 0; + // Create a map associating each non-maximal k-faces to the list of its + // maximal cofaces + Cofaces_map cofaces_map; + for (Complex::const_iterator it_simplex = m_complex.begin(), + it_simplex_end = m_complex.end() ; + it_simplex != it_simplex_end ; + ++it_simplex) { - std::vector k_faces; - // Get the k-faces composing the simplex - combinations(*it_simplex, k + 1, std::back_inserter(k_faces)); - for (const auto &comb : k_faces) // CJTODO C++1 - cofaces_map[comb].push_back(it_simplex); - } - } - - // For each non-maximal k-face F, if F has only one maximal coface Cf: - // - Look for the other k-faces F2, F3... of Cf in the map and: - // * if the list contains only Cf, clear the list (we don't remove the - // list since it creates troubles with the iterators) and add the F2, - // F3... to the complex - // * otherwise, remove Cf from the associated list - // - Remove Cf from the complex - for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(), - it_map_end = cofaces_map.end() ; - it_map_elt != it_map_end ; - ++it_map_elt) - { - if (it_map_elt->second.size() == 1) - { - std::vector k_faces; - const Simplex_iterator_list::value_type &it_Cf = - *it_map_elt->second.begin(); - CGAL_assertion(it_Cf->size() == max_simplex_dim + 1); - // Get the k-faces composing the simplex - combinations(*it_Cf, k + 1, std::back_inserter(k_faces)); - for (const auto &f2 : k_faces) // CJTODO C++1 + if (it_simplex->size() > k + 1) { - // Skip F - if (f2 != it_map_elt->first) + std::vector k_faces; + // Get the k-faces composing the simplex + combinations(*it_simplex, k + 1, std::back_inserter(k_faces)); + for (const auto &comb : k_faces) // CJTODO C++1 + cofaces_map[comb].push_back(it_simplex); + } + } + + // For each non-maximal k-face F, if F has only one maximal coface Cf: + // - Look for the other k-faces F2, F3... of Cf in the map and: + // * if the list contains only Cf, clear the list (we don't remove the + // list since it creates troubles with the iterators) and add the F2, + // F3... to the complex + // * otherwise, remove Cf from the associated list + // - Remove Cf from the complex + for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(), + it_map_end = cofaces_map.end() ; + it_map_elt != it_map_end ; + ++it_map_elt) + { + if (it_map_elt->second.size() == 1) + { + std::vector k_faces; + const Simplex_iterator_list::value_type &it_Cf = + *it_map_elt->second.begin(); + CGAL_assertion(it_Cf->size() == max_simplex_dim + 1); + // Get the k-faces composing the simplex + combinations(*it_Cf, k + 1, std::back_inserter(k_faces)); + for (const auto &f2 : k_faces) // CJTODO C++1 { - Cofaces_map::iterator it_comb_in_map = cofaces_map.find(f2); - if (it_comb_in_map->second.size() == 1) + // Skip F + if (f2 != it_map_elt->first) { - it_comb_in_map->second.clear(); - m_complex.insert(f2); - } - else // it_comb_in_map->second.size() > 1 - { - Simplex_iterator_list::iterator it = std::find( - it_comb_in_map->second.begin(), - it_comb_in_map->second.end(), - it_Cf); - CGAL_assertion(it != it_comb_in_map->second.end()); - it_comb_in_map->second.erase(it); + Cofaces_map::iterator it_comb_in_map = cofaces_map.find(f2); + if (it_comb_in_map->second.size() == 1) + { + it_comb_in_map->second.clear(); + m_complex.insert(f2); + } + else // it_comb_in_map->second.size() > 1 + { + Simplex_iterator_list::iterator it = std::find( + it_comb_in_map->second.begin(), + it_comb_in_map->second.end(), + it_Cf); + CGAL_assertion(it != it_comb_in_map->second.end()); + it_comb_in_map->second.erase(it); + } } } + m_complex.erase(it_Cf); + ++num_collapsed_maximal_simplices; } - m_complex.erase(it_Cf); } - } + // Repeat until no maximal simplex got removed + } while (num_collapsed_maximal_simplices > 0); // Collapse the lower dimension simplices if (k > 0) From 5b0a2a284dce16751aee08435068e3f5befe8ca8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:48:43 +0200 Subject: [PATCH 276/487] Benchmark: added torus + minor fixes --- .../Tangential_complex/benchmark_tc.cpp | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 9cf7efbb3e4..75b43d6c36d 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -164,7 +165,9 @@ bool export_to_off( std::stringstream output_filename; output_filename << "output/" << input_name_stripped << "_" << tc.intrinsic_dimension() << "_in_R" - << tc.ambient_dimension() << suffix << ".off"; + << tc.ambient_dimension() << "_" + << tc.number_of_vertices() << "v" + << suffix << ".off"; std::ofstream off_stream(output_filename.str().c_str()); if (p_complex) @@ -372,6 +375,10 @@ void make_tc(std::vector &points, bool exported = export_to_off(tc, input_name_stripped, "_AFTER_FIX", true); double export_after_perturb_time = (exported ? t.elapsed() : -1); t.reset(); + + //std::string fn = "output/inc_stars/"; + //fn += input_name_stripped; + //tc.export_inconsistent_stars_to_OFF_files(fn); } else { @@ -522,8 +529,8 @@ int main() # endif #endif - int seed = CGAL::default_random.get_int(0, 1<<30); - CGAL::default_random = CGAL::Random(); + int seed = time(NULL); + CGAL::default_random = CGAL::Random(seed); std::cerr << "Random seed = " << seed << std::endl; std::ifstream script_file; @@ -639,6 +646,21 @@ int main() std::atof(param1.c_str()), std::atof(param2.c_str())); } + else if (input == "generate_torus_3D") + { + points = generate_points_on_torus_3D( + num_points, + std::atof(param1.c_str()), + std::atof(param2.c_str()), + param3 == "Y"); + } + else if (input == "generate_torus_d") + { + points = generate_points_on_torus_d( + num_points, + intrinsic_dim, + param1 == "Y"); + } else if (input == "generate_klein_bottle_3D") { points = generate_points_on_klein_bottle_3D( From a015ca547c83247ebb6c923c736aa71f26f1861a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:49:36 +0200 Subject: [PATCH 277/487] Minor optimizations in generate_points_on_torus_d --- Tangential_complex/test/Tangential_complex/test_utilities.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 4847a55c8bc..2bd2ccc5049 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -382,13 +382,11 @@ std::vector generate_points_on_torus_d( Kernel k; CGAL::Random rng; - // if uniform - std::size_t num_slices = (std::size_t)std::pow(num_points, 1./dim); - std::vector points; points.reserve(num_points); if (uniform) { + std::size_t num_slices = (std::size_t)std::pow(num_points, 1./dim); generate_uniform_points_on_torus_d( k, dim, num_slices, std::back_inserter(points)); } @@ -400,6 +398,7 @@ std::vector generate_points_on_torus_d( for (std::size_t i = 0 ; i < num_points ; ) { std::vector pt; + pt.reserve(dim*2); for (int curdim = 0 ; curdim < dim ; ++curdim) { FT alpha = rng.get_double(0, 6.2832); From 045b463cff650325306afa9a3c1bb0f722874f5f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:51:16 +0200 Subject: [PATCH 278/487] export_inconsistent_stars_to_OFF_files --- .../include/CGAL/Tangential_complex.h | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 87278749384..fb8e12dfb3f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -802,6 +802,52 @@ public: return os; } + + // Return a pair + void export_inconsistent_stars_to_OFF_files( + std::string const& filename_base) const + { + std::size_t num_simplices = 0; + std::size_t num_inconsistent_simplices = 0; + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + { + // We build a SC along the way in case it's inconsistent + Simplicial_complex sc; + // For each cell + bool is_inconsistent = false; + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; + ++it_inc_simplex) + { + // Skip infinite cells + if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + continue; + + std::set c = *it_inc_simplex; + c.insert(idx); // Add the missing index + + sc.add_simplex(c); + + // If we do not already know this star is inconsistent, test it + if (!is_inconsistent && !is_simplex_consistent(c)) + is_inconsistent = true; + } + + if (is_inconsistent) + { + // Export star to OFF file + std::stringstream output_filename; + output_filename << filename_base << "_" << idx << ".off"; + std::ofstream off_stream(output_filename.str().c_str()); + export_to_off(sc, off_stream); + } + } + } + bool check_if_all_simplices_are_in_the_ambient_delaunay( const Simplicial_complex *p_complex = NULL, From 002748790e00e60260f743871de4791f223bf1f8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:53:49 +0200 Subject: [PATCH 279/487] Fix perturb (the size of the translation was always m_half_radius) --- .../include/CGAL/Tangential_complex.h | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fb8e12dfb3f..9811d2ceb79 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1703,7 +1703,8 @@ next_face: mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); #ifdef CGAL_TC_PERTURB_TANGENT_SPACE if (perturb) - mat_points(j, i) += m_random_generator.get_double(-0.3, 0.3); + mat_points(j, i) += m_random_generator.get_double( + -m_half_sparsity, m_half_sparsity); #endif } } @@ -2012,18 +2013,17 @@ next_face: typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(m_ambient_dim, 1); + tr_point_on_sphere_generator( + m_ambient_dim, m_random_generator.get_double(0., m_half_sparsity)); // Parallel # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) - Vector transl = k_scaled_vec(k_pt_to_vec(*tr_point_on_sphere_generator++), - m_half_sparsity); + Vector transl = k_pt_to_vec(*tr_point_on_sphere_generator); m_p_perturb_mutexes[point_idx].lock(); m_translations[point_idx] = transl; m_p_perturb_mutexes[point_idx].unlock(); // Sequential # else - m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), m_half_sparsity); + m_translations[point_idx] = k_pt_to_vec(*tr_point_on_sphere_generator); # endif # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL @@ -2038,19 +2038,21 @@ next_face: typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(m_intrinsic_dimension, 1); + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator( + m_intrinsic_dimension, + m_random_generator.get_double(0., m_half_sparsity)); Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( - *tr_point_on_sphere_generator++, 0); + *tr_point_on_sphere_generator, 0); Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_transl = k_transl( global_transl, - k_scaled_vec(tsb[i], m_half_sparsity*coord(local_random_transl, i)) + k_scaled_vec(tsb[i], coord(local_random_transl, i)) ); } // Parallel From 04136b980ce6d8a70920558a2059fa76a2cf965d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:54:58 +0200 Subject: [PATCH 280/487] Improved export to OFF files --- .../include/CGAL/Tangential_complex.h | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 9811d2ceb79..5c7ebc1eeea 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1704,7 +1704,7 @@ next_face: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE if (perturb) mat_points(j, i) += m_random_generator.get_double( - -m_half_sparsity, m_half_sparsity); + -0.5*m_half_sparsity, 0.5*m_half_sparsity); #endif } } @@ -2700,7 +2700,7 @@ next_face: } std::ostream &export_simplices_to_off( - std::ostream & os, std::size_t &num_simplices, + std::ostream & os, std::size_t &num_OFF_simplices, bool color_inconsistencies = false, std::set > const *p_simpl_to_color_in_red = NULL, std::set > const *p_simpl_to_color_in_green = NULL, @@ -2709,8 +2709,9 @@ next_face: { // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) - num_simplices = 0; - std::size_t num_inconsistent_simplices = 0; + num_OFF_simplices = 0; + std::size_t num_maximal_simplices = 0; + std::size_t num_inconsistent_maximal_simplices = 0; std::size_t num_inconsistent_stars = 0; typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); @@ -2743,15 +2744,16 @@ next_face: std::set c = *it_inc_simplex; c.insert(idx); std::size_t num_vertices = c.size(); + ++num_maximal_simplices; int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue - if (color_inconsistencies) + if (color_inconsistencies && !is_simplex_consistent(c)) { - is_star_inconsistent = !is_simplex_consistent(c); - color_simplex = (is_star_inconsistent ? 0 : -1); + ++num_inconsistent_maximal_simplices; + color_simplex = 0; + is_star_inconsistent = true; } - - if (color_simplex == -1) + else { if (p_simpl_to_color_in_red && std::find( @@ -2844,7 +2846,8 @@ next_face: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != idx && color_simplex == -1) + if (*c.begin() != (m_intrinsic_dimension == 1 ? 2*idx : idx) + && color_simplex == -1) continue; os << 3 << " " << sstr_c.str(); @@ -2853,14 +2856,14 @@ next_face: { switch (color_simplex) { - case 0: os << " 255 255 0"; ++num_inconsistent_simplices; break; + case 0: os << " 255 255 0"; break; case 1: os << " 255 0 0"; break; case 2: os << " 0 255 0"; break; case 3: os << " 0 0 255"; break; default: os << " " << color.str(); break; } } - ++num_simplices; + ++num_OFF_simplices; os << std::endl; } if (is_star_inconsistent) @@ -2871,21 +2874,27 @@ next_face: std::cerr << std::endl << "==========================================================" << std::endl - << "Export to OFF:\n" + << "Export from list of stars to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices: " << num_simplices << std::endl - << " * Number of inconsistent stars: " - << num_inconsistent_stars << " (" - << (m_points.size() > 0 ? - 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)" - << std::endl - << " * Number of inconsistent simplices: " - << num_inconsistent_simplices << " (" - << (num_simplices > 0 ? - 100. * num_inconsistent_simplices / num_simplices : 0.) << "%)" - << std::endl - << "==========================================================" + << " * Total number of maximal simplices: " << num_maximal_simplices << std::endl; + if (color_inconsistencies) + { + std::cerr + << " * Number of inconsistent stars: " + << num_inconsistent_stars << " (" + << (m_points.size() > 0 ? + 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)" + << std::endl + << " * Number of inconsistent maximal simplices: " + << num_inconsistent_maximal_simplices << " (" + << (num_maximal_simplices > 0 ? + 100. * num_inconsistent_maximal_simplices / num_maximal_simplices + : 0.) << "%)" + << std::endl; + } + std::cerr << "==========================================================" + << std::endl; #endif return os; @@ -2894,7 +2903,7 @@ next_face: public: std::ostream &export_simplices_to_off( const Simplicial_complex &complex, - std::ostream & os, std::size_t &num_simplices, + std::ostream & os, std::size_t &num_OFF_simplices, std::set > const *p_simpl_to_color_in_red = NULL, std::set > const *p_simpl_to_color_in_green = NULL, std::set > const *p_simpl_to_color_in_blue = NULL) @@ -2905,7 +2914,9 @@ public: // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) - num_simplices = 0; + num_OFF_simplices = 0; + std::size_t num_maximal_simplices = 0; + typename Simplex_range::const_iterator it_s = complex.simplex_range().begin(); typename Simplex_range::const_iterator it_s_end = @@ -2914,6 +2925,7 @@ public: for ( ; it_s != it_s_end ; ++it_s) { Simplex c = *it_s; + ++num_maximal_simplices; int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue if (p_simpl_to_color_in_red && @@ -3018,7 +3030,7 @@ public: } } - ++num_simplices; + ++num_OFF_simplices; os << std::endl; } } @@ -3027,9 +3039,10 @@ public: std::cerr << std::endl << "==========================================================" << std::endl - << "Export to OFF:\n" + << "Export from complex to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices: " << num_simplices << std::endl + << " * Total number of maximal simplices: " << num_maximal_simplices + << std::endl << "==========================================================" << std::endl; #endif From c1c3e3c58bab7b1bd7bd0d11cff7cdb54833129c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:55:33 +0200 Subject: [PATCH 281/487] Updated benchmark script --- .../Tangential_complex/benchmark_script.txt | 93 +++++++++++-------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 1b050e0eccf..3deaec7d390 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -2,54 +2,69 @@ # Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- -#---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- -#generate_sphere_d 4 - - 20 3 2 0.05 N N Y 60 1 -#generate_sphere_d 3 - - 70 3 2 0.05 Y Y Y 60 1 -#generate_sphere_d 3 - - 1000 3 2 0.05 Y Y Y 60 1 -#generate_sphere_d 3 - - 70 4 3 0.05 Y Y Y 60 1 -#generate_sphere_d 3 - - 70 5 4 0.05 Y Y Y 60 1 -#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 Y Y Y 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.7 Y Y Y 60 1 -#generate_moment_curve 0 1 - 30 3 1 0.005 Y Y Y 60 1 - #---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ #generate_sphere_d 0.302 - - 70 2 1 0.005 N N Y 60 1 #generate_sphere_d 0.5 - - 70 2 1 0.005 N N Y 60 1 -generate_sphere_d 3 2 - 100 3 2 0.05 N N Y 60 1 -#generate_klein_bottle_4D 40 15 - 130 4 2 0.2 N N Y 60 1 -#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 Y Y Y 60 1 #Takes forever +#generate_sphere_d 3 2 - 1000 3 2 0.05 N N Y 60 1 +#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N Y 60 1 +#generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N Y 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever + +#---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- +#generate_sphere_d 4 - - 20 3 2 0.05 N Y N 60 1 +#generate_sphere_d 3 - - 70 3 2 0.05 N Y N 60 1 +#generate_sphere_d 3 - - 1000 3 2 0.05 N Y N 60 1 +#generate_sphere_d 3 - - 70 4 3 0.05 N Y N 60 1 +#generate_sphere_d 3 - - 70 5 4 0.05 N Y N 60 1 +#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 N Y N 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.7 N Y N 60 1 +#generate_moment_curve 0 1 - 30 3 1 0.005 N Y N 60 1 +#generate_torus_3D 2 1 Y 150 3 2 0.05 Y N N 600 1 +#generate_torus_d N - - 30 2 1 0.01 Y N N 30 1 +#generate_torus_d Y - - 70 4 2 0.05 Y N N 30 1 +#generate_torus_d N - - 200 4 2 0.05 Y N N 30 1 +#generate_torus_d N - - 20000 4 2 0.65 Y N N 30 1 +#generate_torus_d N - - 10000 6 3 0.05 Y N N 300 1 +#generate_torus_d N - - 50000 6 3 0.05 Y N N 7000 1 +#generate_torus_d N - - 100000 6 3 0.05 Y N N 7000 1 +generate_torus_d N - - 1000000 6 3 0.3 Y N N 3000 1 +#generate_torus_d Y - - 10000 8 4 0.05 Y N N 3600 1 #------------------------------------------------------------------ From files -------------------------------------------------------------------------- -#data/SO3_50000.txt - - - 0 9 3 0.2 Y Y Y 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.05 Y Y Y 60 1 -#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 Y Y Y 3000 1 -#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 Y Y Y 3000 1 -#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 Y Y Y 3000 1 -#data/Cy8.txt - - - 0 24 2 0.1 Y Y Y 60 1 -#data/Kl.txt - - - 0 5 2 0.05 Y Y Y 60 1 -#data/S3.txt - - - 0 4 3 0.05 Y Y Y 60 1 +#data/SO3_50000.txt - - - 0 9 3 0.05 Y Y N 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.05 Y N N 60 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 N Y N 3000 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 N Y N 3000 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 N Y N 3000 1 +#data/Cy8.txt - - - 0 24 2 0.1 N Y N 60 1 +#data/Kl.txt - - - 0 5 2 0.05 N Y N 60 1 +#data/S3.txt - - - 0 4 3 0.05 N Y N 60 1 #---------------------------------------------------------------------- 3D meshes ----------------------------------------------------------------------- -#data/buddha_100kv.txt - - - 0 3 2 0.005 Y Y Y 60 1 -#data/fandisk.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/fertility.txt - - - 0 3 2 0.4 Y Y Y 60 1 -#data/bunny.txt - - - 0 3 2 0.5 Y Y Y 60 1 -#data/blob.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/3holes.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/785_hand_2500v.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/785_hand_50kv.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/bumpy_sphere.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/buddha_100kv.txt - - - 0 3 2 0.005 N Y N 120 1 +#data/fandisk.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/fertility.txt - - - 0 3 2 0.4 N Y N 60 1 +#data/bunny.txt - - - 0 3 2 0.5 N Y N 60 1 +#data/blob.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/3holes.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/785_hand_2500v.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/785_hand_50kv.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/bumpy_sphere.txt - - - 0 3 2 0.01 N Y N 60 1 #----------------------------------------------------------- Generated point sets ----------------------------------------------------------------------- -#generate_sphere_d 3 - - 4 3 2 0.05 Y Y Y 3000 1 -#generate_sphere_d 3 - - 30000 2 1 0.005 Y Y Y 3000 1 -#generate_sphere_d 3 - - 30000 3 2 0.005 Y Y Y 3000 1 -#generate_sphere_d 3 - - 30000 4 3 0.05 Y Y Y 3000 1 -#generate_plane - - - 30000 3 2 0.005 Y Y Y 3000 1 -#generate_moment_curve 0 1 - 30000 6 1 0.005 Y Y Y 60 1 -#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 Y Y Y 60 1 -#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 Y Y Y 60 1 +#generate_sphere_d 3 - - 4 3 2 0.05 N Y N 3000 1 +#generate_sphere_d 3 - - 30000 2 1 0.005 N Y N 3000 1 +#generate_sphere_d 3 - - 30000 3 2 0.005 N Y N 3000 1 +#generate_sphere_d 3 - - 30000 4 3 0.05 N Y N 3000 1 +#generate_sphere_d 3 0 - 3000 3 2 0.005 N Y N 60 1 +#generate_sphere_d 3 4 - 3000 3 2 0.005 N Y N 60 1 +#generate_sphere_d 3 7 - 3000 3 2 0.005 N Y N 60 1 +#generate_plane - - - 30000 3 2 0.005 N Y N 3000 1 +#generate_moment_curve 0 1 - 30000 6 1 0.005 N Y N 60 1 +#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 N Y N 60 1 +#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 N Y N 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever #----------------------------------------------------------- Performance testing ------------------------------------------------------------------------ # TC: 5.55 / 1st fix step : 0.2 -#data/fertility.txt - - - 0 3 2 0.1 Y Y Y 100 1 \ No newline at end of file +#data/fertility.txt - - - 0 3 2 0.1 N Y N 100 1 \ No newline at end of file From f84b0ed529e294e1d835875efd3ea9100d99bb62 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 28 May 2015 17:04:17 +0200 Subject: [PATCH 282/487] Add a spatial searching benchmarking function in test_utilities.h Updated Point_cloud.h to use nanoflann correctly --- .../Tangential_complex/benchmark_script.txt | 26 +- .../Tangential_complex/benchmark_tc.cpp | 9 +- .../CGAL/Tangential_complex/Point_cloud.h | 341 +++++++++--------- .../include/CGAL/Tangential_complex/config.h | 2 +- .../test/Tangential_complex/test_utilities.h | 73 ++++ 5 files changed, 261 insertions(+), 190 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 3deaec7d390..fa30a289ffd 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -9,6 +9,22 @@ #generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N Y 60 1 #generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N Y 60 1 #generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever +#generate_torus_3D 2 1 Y 150 3 2 0.05 Y N N 600 1 +#generate_torus_d N - - 30 2 1 0.01 Y N N 30 1 +#generate_torus_d Y - - 70 4 2 0.05 Y N N 30 1 +#generate_torus_d N - - 200 4 2 0.05 Y N N 30 1 +#generate_torus_d N - - 20000 4 2 0.65 Y N N 30 1 +#generate_torus_d N - - 10000 6 3 0.05 Y N N 300 1 +#generate_torus_d N - - 50000 6 3 0.05 Y N N 7000 1 +#generate_torus_d N - - 100000 6 3 0.05 Y N N 7000 1 +#generate_torus_d N - - 1000000 6 3 0.3 Y N N 3000 1 +#generate_torus_d Y - - 10000 8 4 0.05 Y N N 3600 1 + +#---------------------------------------------------------- Spatial search benchmarking -------------------------------------------------------------- +generate_torus_d Y - - 1000000 30 15 0 Y N N 3600 1 +data/SO3_50000.txt - - - 0 9 3 0 Y Y N 60 1 +data/Cy8.txt - - - 0 24 2 0 N Y N 60 1 +data/buddha_100kv.txt - - - 0 3 2 0 N Y N 120 1 #---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- #generate_sphere_d 4 - - 20 3 2 0.05 N Y N 60 1 @@ -19,16 +35,6 @@ #generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 N Y N 60 1 #data/SO3_10000.txt - - - 0 9 3 0.7 N Y N 60 1 #generate_moment_curve 0 1 - 30 3 1 0.005 N Y N 60 1 -#generate_torus_3D 2 1 Y 150 3 2 0.05 Y N N 600 1 -#generate_torus_d N - - 30 2 1 0.01 Y N N 30 1 -#generate_torus_d Y - - 70 4 2 0.05 Y N N 30 1 -#generate_torus_d N - - 200 4 2 0.05 Y N N 30 1 -#generate_torus_d N - - 20000 4 2 0.65 Y N N 30 1 -#generate_torus_d N - - 10000 6 3 0.05 Y N N 300 1 -#generate_torus_d N - - 50000 6 3 0.05 Y N N 7000 1 -#generate_torus_d N - - 100000 6 3 0.05 Y N N 7000 1 -generate_torus_d N - - 1000000 6 3 0.3 Y N N 3000 1 -#generate_torus_d Y - - 10000 8 4 0.05 Y N N 3600 1 #------------------------------------------------------------------ From files -------------------------------------------------------------------------- #data/SO3_50000.txt - - - 0 9 3 0.05 Y Y N 60 1 diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 75b43d6c36d..ef4863051cf 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -210,6 +210,8 @@ void make_tc(std::vector &points, double time_limit_for_perturb = 0., const char *input_name = "tc") { + Kernel k; + // CJTODO TEMP TEST //TC::Simplicial_complex compl; //{std::size_t ss[] = {0, 1, 2}; compl.add_simplex(std::set(ss, ss + 3)); } @@ -232,10 +234,13 @@ void make_tc(std::vector &points, //compl.is_pure_pseudomanifold(3, 9, false, 10); // /CJTODO TEMP TEST + // CJTODO TEMP TEST + benchmark_spatial_search(points, k); + return; + //=========================================================================== // Init //=========================================================================== - Kernel k; Wall_clock_timer t; // Get input_name_stripped @@ -529,7 +534,7 @@ int main() # endif #endif - int seed = time(NULL); + unsigned int seed = static_cast(time(NULL)); CGAL::default_random = CGAL::Random(seed); std::cerr << "Random seed = " << seed << std::endl; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 0ea59a5f208..18452493061 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -22,183 +22,8 @@ #define POINT_CLOUD_H #include -#include #include -#ifdef CGAL_TC_USE_NANOFLANN - -#include "nanoflann.hpp" - -#include -#include -#include - -namespace CGAL { -namespace Tangential_complex_ { - -// "dataset to kd-tree" adaptor class -template -class Point_cloud_adaptator -{ -public: - typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - - /// The constructor that sets the data set source - Point_cloud_adaptator(Point_container_ &points, Kernel const& k) - : m_points(points), m_k(k) - {} - - /// CRTP helper method - inline Point_container_ const& points() const - { - return m_points; - } - inline Point_container_& points() - { - return m_points; - } - - // Must return the number of data points - inline size_t kdtree_get_point_count() const - { - return m_points.size(); - } - - // Returns the distance between the vector "p1[0:size-1]" - // and the data point with index "idx_p2" stored in the class: - inline FT kdtree_distance( - const FT *p1, const size_t idx_p2, size_t size) const - { - Point sp(p1, p1 + size); - return m_k.squared_distance_d_object()(sp, points()[idx_p2]); - } - - // Returns the dim'th component of the idx'th point in the class: - // Since this is inlined and the "dim" argument is typically an - // immediate value, the "if/else's" are actually solved at compile time. - inline FT kdtree_get_pt(const size_t idx, int dim) const - { - return m_k.compute_coordinate_d_object()(points()[idx], dim); - } - - // Optional bounding-box computation: return false to default to a standard - // bbox computation loop. - // Return true if the BBOX was already computed by the class and returned - // in "bb" so it can be avoided to redo it again. - // Look at bb.size() to find out the expected dimensionality - // (e.g. 2 or 3 for point clouds) - template - bool kdtree_get_bbox(Bbox &bb) const - { - return false; - } - - Kernel const& kernel() const - { - return m_k; - } - -protected: - Point_container_& m_points; //!< A ref to the data set origin - Kernel const& m_k; //!< A const ref to the kernel - -}; - -template -class Point_cloud_data_structure -{ -public: - typedef typename Point_container_::value_type Point; - typedef typename K Kernel; - typedef typename Kernel::FT FT; - - static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar - - /// Constructor - /// "points" must not be empty - Point_cloud_data_structure(Point_container_ &points, Kernel const& k) - : m_adaptor(points, k), - m_kd_tree(k.point_dimension_d_object()(*points.begin()), - m_adaptor, - nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) - { - m_kd_tree.buildIndex(); - } - - /*Point_container_ &points() - { - return m_adaptor.points(); - } - - const Point_container_ &points() const - { - return m_adaptor.points(); - }*/ - - void query_ANN(const Point &sp, - std::size_t k, - size_t *neighbor_indices, - FT *squared_distance) const - { - std::vector sp_vec( - m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), - m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0)); - nanoflann::KNNResultSet result_set(k); - result_set.init(neighbor_indices, squared_distance); - m_kd_tree.findNeighbors(result_set, - &sp_vec[0], - nanoflann::SearchParams()); - - /*std::cout << "knnSearch(nn="<< num_results <<"): \n"; - for (int i = 0 ; i < num_results ; ++i) - { - std::cout << " * neighbor_indices = " << neighbor_indices [i] - << " (out_dist_sqr = " << squared_distance[i] << ")" - << std::endl; - }*/ - } - - void query_ball(const Point &sp, - const FT radius, - std::vector > &neighbors, - bool sort_output = true) - { - std::vector sp_vec( - m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), - m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0)); - m_kd_tree.radiusSearch(&sp_vec[0], - radius, - neighbors, - nanoflann::SearchParams(32, 0.f, sort_output)); - - /*std::cout << "radiusSearch(num="<< neighbors.size() <<"): \n"; - for (const auto idx_and_dist : neighbors) - { - std::cout << " * neighbor_indices = " << idx_and_dist.first - << " (out_dist_sqr = " << idx_and_dist.second << ")" - << std::endl; - }*/ - } - -protected: - typedef Point_cloud_adaptator Adaptor; - typedef nanoflann::KDTreeSingleIndexAdaptor< - nanoflann::L2_Simple_Adaptor , - Adaptor, - AMB_DIM // dim - > Kd_tree; - - Adaptor m_adaptor; - Kd_tree m_kd_tree; -}; - -} // namespace Tangential_complex_ -} //namespace CGAL - -#else // !CGAL_TC_USE_NANOFLANN => use CGAL Spatial searching - #include #include #include @@ -211,7 +36,6 @@ protected: #include #include -#include namespace CGAL { namespace Tangential_complex_ { @@ -325,9 +149,172 @@ protected: Tree m_tree; }; + +#ifdef CGAL_TC_NANOFLANN_IS_AVAILABLE + +#include "nanoflann.hpp" + +// "dataset to kd-tree" adaptor class +template +class Point_cloud_adaptator__nanoflann +{ +public: + typedef typename Point_container_::value_type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + /// The constructor that sets the data set source + Point_cloud_adaptator__nanoflann(const Point_container_ &points, Kernel const& k) + : m_points(points), m_k(k) + {} + + /// CRTP helper method + inline Point_container_ const& points() const + { + return m_points; + } + inline Point_container_& points() + { + return m_points; + } + + // Must return the number of data points + inline size_t kdtree_get_point_count() const + { + return m_points.size(); + } + + // Returns the distance between the vector "p1[0:size-1]" + // and the data point with index "idx_p2" stored in the class: + inline FT kdtree_distance( + const FT *p1, const size_t idx_p2, size_t size) const + { + Point sp(p1, p1 + size); + return m_k.squared_distance_d_object()(sp, points()[idx_p2]); + } + + // Returns the dim'th component of the idx'th point in the class: + // Since this is inlined and the "dim" argument is typically an + // immediate value, the "if/else's" are actually solved at compile time. + inline FT kdtree_get_pt(const size_t idx, int dim) const + { + return m_k.compute_coordinate_d_object()(points()[idx], dim); + } + + // Optional bounding-box computation: return false to default to a standard + // bbox computation loop. + // Return true if the BBOX was already computed by the class and returned + // in "bb" so it can be avoided to redo it again. + // Look at bb.size() to find out the expected dimensionality + // (e.g. 2 or 3 for point clouds) + template + bool kdtree_get_bbox(Bbox &bb) const + { + return false; + } + + Kernel const& kernel() const + { + return m_k; + } + +protected: + Point_container_ const& m_points; //!< A const ref to the data set origin + Kernel const& m_k; //!< A const ref to the kernel + +}; + +template +class Point_cloud_data_structure__nanoflann +{ +public: + typedef typename Point_container_::value_type Point; + typedef typename K Kernel; + typedef typename Kernel::FT FT; + + /// Constructor + /// "points" must not be empty + Point_cloud_data_structure__nanoflann( + Point_container_ const& points, Kernel const& k) + : m_adaptor(points, k), + m_kd_tree(k.point_dimension_d_object()(*points.begin()), + m_adaptor, + nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) + { + m_kd_tree.buildIndex(); + } + + /*Point_container_ &points() + { + return m_adaptor.points(); + } + + const Point_container_ &points() const + { + return m_adaptor.points(); + }*/ + + void query_ANN(const Point &sp, + std::size_t k, + size_t *neighbor_indices, + FT *squared_distance) const + { + std::vector sp_vec( + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0)); + nanoflann::KNNResultSet result_set(k); + result_set.init(neighbor_indices, squared_distance); + m_kd_tree.findNeighbors(result_set, + &sp_vec[0], + nanoflann::SearchParams()); + + /*std::cout << "knnSearch(nn="<< num_results <<"): \n"; + for (int i = 0 ; i < num_results ; ++i) + { + std::cout << " * neighbor_indices = " << neighbor_indices [i] + << " (out_dist_sqr = " << squared_distance[i] << ")" + << std::endl; + }*/ + } + + void query_ball(const Point &sp, + const FT radius, + std::vector > &neighbors, + bool sort_output = true) + { + std::vector sp_vec( + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0)); + m_kd_tree.radiusSearch(&sp_vec[0], + radius, + neighbors, + nanoflann::SearchParams(32, 0.f, sort_output)); + + /*std::cout << "radiusSearch(num="<< neighbors.size() <<"): \n"; + for (const auto idx_and_dist : neighbors) + { + std::cout << " * neighbor_indices = " << idx_and_dist.first + << " (out_dist_sqr = " << idx_and_dist.second << ")" + << std::endl; + }*/ + } + +protected: + typedef Point_cloud_adaptator__nanoflann Adaptor; + typedef nanoflann::KDTreeSingleIndexAdaptor< + nanoflann::L2_Simple_Adaptor , + Adaptor, + -1 // dim + > Kd_tree; + + Adaptor m_adaptor; + Kd_tree m_kd_tree; +}; + +#endif //CGAL_TC_NANOFLANN_IS_AVAILABLE + } // namespace Tangential_complex_ } //namespace CGAL -#endif // CGAL_TC_USE_NANOFLANN #endif // POINT_CLOUD_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 060b1b75feb..9053edefd5a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -50,7 +50,7 @@ //========================= Strategy ========================================== -//#define CGAL_TC_USE_NANOFLANN +#define CGAL_TC_NANOFLANN_IS_AVAILABLE //#define CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER #define CGAL_TC_GLOBAL_REFRESH //#define CGAL_TC_ON_DEMAND_REFRESH // CJTODO: not implemented yet diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 2bd2ccc5049..d3df879a0d7 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -615,4 +615,77 @@ generate_points_on_klein_bottle_variant_5D( return points; } +template +void benchmark_spatial_search( + const std::vector &points, const Kernel &k) +{ + std::cout << + "****************************************\n" + "***** Benchmarking spatial search ******\n" + "****************************************\n\n"; + + const std::size_t NUM_QUERIES = 100000; + const std::size_t NUM_NEIGHBORS = 50; + + typedef Kernel::FT FT; + typedef Kernel::Point_d Point; + typedef std::vector Points; + + CGAL::Random random_generator; + Wall_clock_timer t; + + //****************************** CGAL *************************************** + { + std::cout << "\n=== CGAL ===\n"; + + typedef CGAL::Tangential_complex_::Point_cloud_data_structure + Points_ds; + typedef Points_ds::KNS_range KNS_range; + typedef Points_ds::KNS_iterator KNS_iterator; + typedef Points_ds::INS_range INS_range; + typedef Points_ds::INS_iterator INS_iterator; + + t.reset(); + Points_ds points_ds(points); + double init_time = t.elapsed(); + std::cout << "Init: " << init_time << std::endl; + t.reset(); + + for (std::size_t i = 0 ; i < NUM_QUERIES ; ++i) + { + std::size_t pt_idx = random_generator.get_int(0, points.size() - 1); + KNS_range kns_range = points_ds.query_ANN( + points[pt_idx], NUM_NEIGHBORS, true); + } + double queries_time = t.elapsed(); + std::cout << NUM_QUERIES << " queries among " + << points.size() << " points: " << queries_time << std::endl; + } + //**************************** nanoflann ************************************ + { + std::cout << "\n=== nanoflann ===\n"; + + typedef CGAL::Tangential_complex_:: + Point_cloud_data_structure__nanoflann + Points_ds; + + t.reset(); + Points_ds points_ds(points, k); + double init_time = t.elapsed(); + std::cout << "Init: " << init_time << std::endl; + t.reset(); + + for (std::size_t i = 0 ; i < NUM_QUERIES ; ++i) + { + std::size_t pt_idx = random_generator.get_int(0, points.size() - 1); + std::size_t neighbors_indices[NUM_NEIGHBORS]; + FT neighbors_sq_distances[NUM_NEIGHBORS]; + points_ds.query_ANN( + points[pt_idx], NUM_NEIGHBORS, neighbors_indices, neighbors_sq_distances); + } + double queries_time = t.elapsed(); + std::cout << NUM_QUERIES << " queries among " + << points.size() << " points: " << queries_time << std::endl; + } +} #endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H From b1e98606895b94cde824005da09d66d48b613d03 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 29 May 2015 14:58:09 +0200 Subject: [PATCH 283/487] Fix point set creation timing + #ifdef for KNN benchmark --- .../Tangential_complex/benchmark_tc.cpp | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ef4863051cf..53f6c499246 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -39,6 +39,12 @@ typedef CGAL::Tangential_complex< Kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag> TC; +//#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test + +#ifdef JUST_BENCHMARK_SPATIAL_SEARCH +std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); +#endif + class XML_perf_data { public: @@ -234,9 +240,10 @@ void make_tc(std::vector &points, //compl.is_pure_pseudomanifold(3, 9, false, 10); // /CJTODO TEMP TEST - // CJTODO TEMP TEST - benchmark_spatial_search(points, k); +#ifdef JUST_BENCHMARK_SPATIAL_SEARCH + benchmark_spatial_search(points, k, spatial_search_csv_file); return; +#endif //=========================================================================== // Init @@ -257,15 +264,6 @@ void make_tc(std::vector &points, int ambient_dim = k.point_dimension_d_object()(*points.begin()); -#ifdef CGAL_TC_PROFILING - Wall_clock_timer t_gen; -#endif - -#ifdef CGAL_TC_PROFILING - std::cerr << "Point set generated in " << t_gen.elapsed() - << " seconds." << std::endl; -#endif - CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM @@ -631,6 +629,10 @@ int main() #endif std::cerr << std::endl << "TC #" << i << "..." << std::endl; + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_gen; +#endif std::vector points; @@ -690,6 +692,11 @@ int main() input, std::back_inserter(points)/*, 600*/); } +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set generated/loaded in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif + if (!points.empty()) { make_tc(points, intrinsic_dim, sparsity, From 67e9c3a6919cb6ebc66423ac165ac5417a3e7f9a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Jun 2015 17:54:14 +0200 Subject: [PATCH 284/487] New generators + benchmark ANN --- .../Tangential_complex/benchmark_tc.cpp | 16 ++ .../test/Tangential_complex/test_utilities.h | 160 +++++++++++++++++- 2 files changed, 173 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 53f6c499246..ef920ed2f2f 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -653,6 +653,22 @@ int main() std::atof(param1.c_str()), std::atof(param2.c_str())); } + else if (input == "generate_two_spheres_d") + { + points = generate_points_on_two_spheres_d( + num_points, ambient_dim, + std::atof(param1.c_str()), + std::atof(param2.c_str()), + std::atof(param3.c_str())); + } + else if (input == "generate_3sphere_and_circle_d") + { + CGAL_assertion(intrinsic_dim == 3); + CGAL_assertion(ambient_dim == 5); + points = generate_points_on_3sphere_and_circle( + num_points, + std::atof(param1.c_str())); + } else if (input == "generate_torus_3D") { points = generate_points_on_torus_3D( diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index d3df879a0d7..1b0d0ff4ed1 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -300,14 +300,18 @@ std::vector generate_points_on_moment_curve( // R = big radius, r = small radius -template +template std::vector generate_points_on_torus_3D( - std::size_t num_points, double R, double r, bool uniform = false) + std::size_t num_points, double R, double r, bool uniform = false + /*, std::vector *p_tangent_planes = NULL*/) { typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; typedef typename Kernel::FT FT; Kernel k; CGAL::Random rng; + + //typename Kernel::Construct_vector_d cstr_vec = k.construct_vector_d_object(); // if uniform std::size_t num_lines = (std::size_t)sqrt(num_points); @@ -345,6 +349,20 @@ std::vector generate_points_on_torus_3D( points.push_back(p); ++i; #endif + /*if (p_tangent_planes) + { + TC_basis tp(p); + tp.push_back(cstr_vec( + -r * std::cos(v) * std::sin(u), + -r * std::sin(v) * std::sin(u), + r * std::cos(u))); + tp.push_back(cstr_vec( + -(R + r * std::cos(u)) * std::sin(v), + (R + r * std::cos(u)) * std::cos(v), + 0)); + p_tangent_planes->push_back( + CGAL::Tangential_complex_::compute_gram_schmidt_basis(sp, k)); + }*/ } return points; } @@ -461,6 +479,111 @@ std::vector generate_points_on_sphere_d( return points; } +template +std::vector generate_points_on_two_spheres_d( + std::size_t num_points, int dim, double radius, + double distance_between_centers, double radius_noise_percentage = 0.) +{ + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + Kernel k; + CGAL::Random rng; + CGAL::Random_points_on_sphere_d generator(dim, radius); + std::vector points; + points.reserve(num_points); + + std::vector t(dim, FT(0)); + t[0] = distance_between_centers; + Vector c1_to_c2(t.begin(), t.end()); + +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + Point p = *generator++; + if (radius_noise_percentage > 0.) + { + double radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage)/100., + (100. + radius_noise_percentage)/100.); + + typename Kernel::Point_to_vector_d k_pt_to_vec = + k.point_to_vector_d_object(); + typename Kernel::Vector_to_point_d k_vec_to_pt = + k.vector_to_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + k.scaled_vector_d_object(); + p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio)); + } + + typename Kernel::Translated_point_d k_transl = + k.translated_point_d_object(); + Point p2 = k_transl(p, c1_to_c2); + +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + if (sparsifier.try_to_insert_point(p)) + ++i; + if (sparsifier.try_to_insert_point(p2)) + ++i; +#else + points.push_back(p); + points.push_back(p2); + i += 2; +#endif + } + return points; +} + +// Product of a 3-sphere and a circle => d = 3 / D = 5 +template +std::vector generate_points_on_3sphere_and_circle( + std::size_t num_points, double sphere_radius) +{ + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + Kernel k; + CGAL::Random rng; + CGAL::Random_points_on_sphere_d generator(3, sphere_radius); + std::vector points; + points.reserve(num_points); + + typename Kernel::Translated_point_d k_transl = + k.translated_point_d_object(); + typename Kernel::Compute_coordinate_d k_coord = + k.compute_coordinate_d_object(); + +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + Point p_sphere = *generator++; // First 3 coords + + FT alpha = rng.get_double(0, 6.2832); + std::vector pt(5); + pt[0] = k_coord(p_sphere, 0); + pt[1] = k_coord(p_sphere, 1); + pt[2] = k_coord(p_sphere, 2); + pt[3] = std::cos(alpha); + pt[4] = std::sin(alpha); + Point p(pt.begin(), pt.end()); + +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + if (sparsifier.try_to_insert_point(p)) + ++i; + if (sparsifier.try_to_insert_point(p2)) + ++i; +#else + points.push_back(p); + ++i; +#endif + } + return points; +} + // a = big radius, b = small radius template std::vector generate_points_on_klein_bottle_3D( @@ -617,7 +740,8 @@ generate_points_on_klein_bottle_variant_5D( template void benchmark_spatial_search( - const std::vector &points, const Kernel &k) + const std::vector &points, const Kernel &k, + std::ostream & csv_file) { std::cout << "****************************************\n" @@ -660,6 +784,7 @@ void benchmark_spatial_search( double queries_time = t.elapsed(); std::cout << NUM_QUERIES << " queries among " << points.size() << " points: " << queries_time << std::endl; + csv_file << queries_time << ";"; } //**************************** nanoflann ************************************ { @@ -686,6 +811,35 @@ void benchmark_spatial_search( double queries_time = t.elapsed(); std::cout << NUM_QUERIES << " queries among " << points.size() << " points: " << queries_time << std::endl; + csv_file << queries_time << ";"; + } + + //******************************* ANN *************************************** + { + std::cout << "\n=== ANN ===\n"; + + typedef CGAL::Tangential_complex_:: + Point_cloud_data_structure__ANN + Points_ds; + + t.reset(); + Points_ds points_ds(points, k); + double init_time = t.elapsed(); + std::cout << "Init: " << init_time << std::endl; + t.reset(); + + for (std::size_t i = 0 ; i < NUM_QUERIES ; ++i) + { + std::size_t pt_idx = random_generator.get_int(0, points.size() - 1); + int neighbors_indices[NUM_NEIGHBORS]; + double neighbors_sq_distances[NUM_NEIGHBORS]; + points_ds.query_ANN( + points[pt_idx], NUM_NEIGHBORS, neighbors_indices, neighbors_sq_distances); + } + double queries_time = t.elapsed(); + std::cout << NUM_QUERIES << " queries among " + << points.size() << " points: " << queries_time << std::endl; + csv_file << queries_time << "\n"; } } #endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H From 5341a983c289b695249fe3136ef0f3537a7918bf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Jun 2015 14:31:30 +0200 Subject: [PATCH 285/487] Add check_correlation_between_inconsistencies_and_fatness --- .../include/CGAL/Tangential_complex.h | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5c7ebc1eeea..19a10e02213 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -1931,6 +1932,61 @@ next_face: } return is_simplex_consistent(c); } + + // A simplex here is a list of point indices + template + double compute_simplex_fatness(IndexRange const& simplex) const + { + // Kernel functors + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename Kernel::Squared_distance_d sqdist = + m_k.squared_distance_d_object(); + typename Kernel::Difference_of_points_d diff_pts = + m_k.difference_of_points_d_object(); + + typename Tr_traits::Difference_of_points_d tr_diff_pts = + m_triangulations[0].tr().geom_traits().difference_of_points_d_object(); + + std::vector s(simplex.begin(), simplex.end()); + + // Compute basis + Tangent_space_basis basis(m_points[s[0]]); + for (int j = 0 ; j < m_intrinsic_dimension ; ++j) + { + Vector e = diff_pts( + m_points[s[j+1]], m_points[s[0]]); + basis.push_back(e); + } + basis = compute_gram_schmidt_basis(basis, m_k); + + // Compute the volume of the simplex: determinant + Eigen::MatrixXd m(m_intrinsic_dimension, m_intrinsic_dimension); + for (int j = 0 ; j < m_intrinsic_dimension ; ++j) + { + Tr_vector v_j = tr_diff_pts( + project_point(m_points[s[j+1]], basis), + project_point(m_points[s[0]], basis)); + for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + m(j, i) = CGAL::to_double(coord(v_j, i)); + } + double volume = + std::abs(m.determinant()) + / boost::math::factorial(m_intrinsic_dimension); + + // Compute the longest edge of the simplex + CGAL::Combination_enumerator combi(2, 0, m_intrinsic_dimension+1); + FT max_sq_length = FT(0); + for ( ; !combi.finished() ; ++combi) + { + FT sq_length = sqdist( + m_points[s[combi[0]]], m_points[s[combi[1]]]); + if (sq_length > max_sq_length) + max_sq_length = sq_length; + } + + return volume / std::pow(CGAL::sqrt(max_sq_length), m_intrinsic_dimension); + } // A simplex here is a list of point indices bool is_simplex_consistent(std::set const& simplex) const @@ -3050,6 +3106,78 @@ public: return os; } + // Return a pair + void check_correlation_between_inconsistencies_and_fatness() const + { + std::ofstream csv_consistent("output/correlation_consistent.csv"); // CJTODO TEMP + std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO TEMP + if (m_intrinsic_dimension < 3) + { + std::cerr << std::endl + << "==========================================================" << std::endl + << "check_correlation_between_inconsistencies_and_slivers():" << std::endl + << "Intrinsic dimension should be >= 3." << std::endl + << "==========================================================" << std::endl + << std::endl; + } + + std::size_t num_consistent_simplices = 0; + double sum_vol_edge_ratio_consistent = 0.; + std::size_t num_inconsistent_simplices = 0; + double sum_vol_edge_ratio_inconsistent = 0.; + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + { + // For each cell + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + // Don't check infinite cells + if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + continue; + + std::set c = *it_inc_simplex; + c.insert(idx); // Add the missing index + + double fatness = compute_simplex_fatness(c); + + if (!is_simplex_consistent(c)) + { + ++num_inconsistent_simplices; + sum_vol_edge_ratio_inconsistent += fatness; + csv_inconsistent << fatness << std::endl; + } + else + { + ++num_consistent_simplices; + sum_vol_edge_ratio_consistent += fatness; + csv_consistent << fatness << std::endl; + } + } + } + + double avg_vol_edge_ratio_inconsistent = + sum_vol_edge_ratio_inconsistent / num_inconsistent_simplices; + double avg_vol_edge_ratio_consistent = + sum_vol_edge_ratio_consistent / num_consistent_simplices; + + std::cerr << std::endl + << "==========================================================" + << std::endl + << "check_correlation_between_inconsistencies_and_slivers()\n" + << " * Avg. volume/longest_edge^d ratio of consistent simplices: " + << avg_vol_edge_ratio_consistent + << " (" << num_consistent_simplices << " simplices)" << std::endl + << " * Avg. volume/longest_edge^d ratio of inconsistent simplices: " + << avg_vol_edge_ratio_inconsistent + << " (" << num_inconsistent_simplices << " simplices)" << std::endl + << "==========================================================" + << std::endl; + } + private: const Kernel m_k; const int m_intrinsic_dimension; From c284f2f626e36e3db3df40dc7fa48cd8e160f414 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 11:28:17 +0200 Subject: [PATCH 286/487] Add ANN option --- .../CGAL/Tangential_complex/Point_cloud.h | 81 +++++++++++++++++-- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 18452493061..6a273ce28fe 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -37,6 +37,14 @@ #include +#ifdef CGAL_TC_ANN_IS_AVAILABLE +# include +#endif + +#ifdef CGAL_TC_NANOFLANN_IS_AVAILABLE +# include "nanoflann.hpp" +#endif + namespace CGAL { namespace Tangential_complex_ { @@ -75,7 +83,10 @@ public: boost::counting_iterator(points.size()), typename Tree::Splitter(), STraits((Point*)&(points[0])) ) - { } + { + // Build the tree now (we don't want to wait for the first query) + m_tree.build(); + } /// Constructor Point_cloud_data_structure( @@ -88,6 +99,8 @@ public: typename Tree::Splitter(), STraits((Point*)&(points[0])) ) { + // Build the tree now (we don't want to wait for the first query) + m_tree.build(); } /*Point_container_ &points() @@ -149,11 +162,12 @@ protected: Tree m_tree; }; +//***************************************************************************** +//***************************************************************************** +//***************************************************************************** #ifdef CGAL_TC_NANOFLANN_IS_AVAILABLE -#include "nanoflann.hpp" - // "dataset to kd-tree" adaptor class template class Point_cloud_adaptator__nanoflann @@ -164,7 +178,7 @@ public: typedef typename Kernel::FT FT; /// The constructor that sets the data set source - Point_cloud_adaptator__nanoflann(const Point_container_ &points, Kernel const& k) + Point_cloud_adaptator__nanoflann(Point_container_ const& points, Kernel const& k) : m_points(points), m_k(k) {} @@ -313,8 +327,65 @@ protected: #endif //CGAL_TC_NANOFLANN_IS_AVAILABLE +//***************************************************************************** +//***************************************************************************** +//***************************************************************************** + +#ifdef CGAL_TC_ANN_IS_AVAILABLE + +template +class Point_cloud_data_structure__ANN +{ +public: + typedef typename Point_container_::value_type Point; + typedef K Kernel; + typedef typename Kernel::FT FT; + + /// Constructor + Point_cloud_data_structure__ANN( + Point_container_ const& points, Kernel const& k) + : m_dim(k.point_dimension_d_object()(*points.begin())), + m_k(k), + m_points(annAllocPts(points.size(), m_dim)), + m_tree(m_points, points.size(), m_dim) + { + for (int i = 0 ; i < points.size() ; ++i) + { + for (int j = 0 ; j < m_dim ; ++j) + m_points[i][j] = m_k.compute_coordinate_d_object()(points[i], j); + } + } + + void query_ANN( + Point const& p, + unsigned int k, + ANNidxArray neighbors_indices, + ANNdistArray neighbors_sq_distances) + { + // Create an ANN query point + ANNpoint query_pt = annAllocPt(m_dim); + for (int j = 0 ; j < m_dim ; ++j) + query_pt[j] = m_k.compute_coordinate_d_object()(p, j); + + m_tree.annkSearch( // search + query_pt, // query point + k, // number of near neighbors + neighbors_indices, // nearest neighbors (returned) + neighbors_sq_distances, // distance (returned) + 0); // error bound + + } + +protected: + int m_dim; + Kernel const& m_k; + ANNpointArray m_points; + ANNkd_tree m_tree; +}; + +#endif // CGAL_TC_ANN_IS_AVAILABLE + } // namespace Tangential_complex_ } //namespace CGAL - #endif // POINT_CLOUD_H From 6e743bc6c58602466af4f57ef09c36557d383d7d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 11:28:52 +0200 Subject: [PATCH 287/487] Add ANN option in config.h --- Tangential_complex/include/CGAL/Tangential_complex/config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 9053edefd5a..19804ffaa84 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -51,6 +51,7 @@ //========================= Strategy ========================================== #define CGAL_TC_NANOFLANN_IS_AVAILABLE +//#define CGAL_TC_ANN_IS_AVAILABLE //#define CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER #define CGAL_TC_GLOBAL_REFRESH //#define CGAL_TC_ON_DEMAND_REFRESH // CJTODO: not implemented yet From 0c5432cd060809a1b56f7d522c5f6cd53c581e52 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 11:30:23 +0200 Subject: [PATCH 288/487] Clean-up debugging code --- .../include/CGAL/Tangential_complex.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 19a10e02213..f96fd626ece 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -68,10 +68,6 @@ //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) //#define CGAL_ALPHA_TC const double ALPHA = 0.3; -#ifdef CGAL_LINKED_WITH_TBB -tbb::atomic ttt_star; // CJTODO TEMP -tbb::atomic ttt_intersect; -#endif //CJTODO: debug //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 @@ -317,8 +313,6 @@ public: { #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) Wall_clock_timer t; - ttt_intersect = 0; - ttt_star = 0; #endif // We need to do that because we don't want the container to copy the @@ -364,8 +358,6 @@ public: #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) std::cerr << "Tangential complex computed in " << t.elapsed() << " seconds." << std::endl; - std::cerr << "Intersect: " << ((double)ttt_intersect)/1000000 << " s\n" - << "Star: " << ((double)ttt_star)/1000000 << " s\n"; #endif } @@ -1440,10 +1432,6 @@ private: } } -#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) - ttt_star += 1000000*t_star.elapsed(); -#endif - //*************************************************** // Parse the faces of the star and add the ones that are in the // restriction to alpha-Tp @@ -1563,9 +1551,6 @@ next_face: does_voronoi_face_and_alpha_tangent_subspace_intersect( m_points, m_weights, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); -#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) - ttt_intersect += 1000000*t_inters.elapsed(); -#endif if (does_intersect) { star.push_back(current_DT_face); From b8914ccb4466facd97f23f076c3cb9a431e235b5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 11:32:31 +0200 Subject: [PATCH 289/487] Use Random_points_in_ball_d --- .../include/CGAL/Tangential_complex.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f96fd626ece..0d87a1bf90c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -2053,18 +2053,18 @@ next_face: # ifdef CGAL_TC_PERTURB_POSITION_GLOBAL typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator( - m_ambient_dim, m_random_generator.get_double(0., m_half_sparsity)); + CGAL::Random_points_in_ball_d + tr_point_in_ball_generator( + m_ambient_dim, m_half_sparsity); // Parallel # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) - Vector transl = k_pt_to_vec(*tr_point_on_sphere_generator); + Vector transl = k_pt_to_vec(*tr_point_in_ball_generator++); m_p_perturb_mutexes[point_idx].lock(); m_translations[point_idx] = transl; m_p_perturb_mutexes[point_idx].unlock(); // Sequential # else - m_translations[point_idx] = k_pt_to_vec(*tr_point_on_sphere_generator); + m_translations[point_idx] = k_pt_to_vec(*tr_point_in_ball_generator++); # endif # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL @@ -2079,14 +2079,14 @@ next_face: typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator( + CGAL::Random_points_in_ball_d + tr_point_in_ball_generator( m_intrinsic_dimension, m_random_generator.get_double(0., m_half_sparsity)); Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( - *tr_point_on_sphere_generator, 0); + *tr_point_in_ball_generator++, 0); Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) From 1be9e245bef9995c8d769440fa9a279c2548739b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 13:22:57 +0200 Subject: [PATCH 290/487] CGAL_ALPHA_TC => CGAL_FIXED_ALPHA_TC --- .../include/CGAL/Tangential_complex.h | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 0d87a1bf90c..4d1e89e3c3a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -66,7 +66,7 @@ #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) -//#define CGAL_ALPHA_TC +//#define CGAL_FIXED_ALPHA_TC const double ALPHA = 0.3; //CJTODO: debug @@ -244,7 +244,7 @@ public: , m_points_ds(m_points) , m_are_tangent_spaces_computed(m_points.size(), false) , m_tangent_spaces(m_points.size(), Tangent_space_basis()) -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) #endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM @@ -285,7 +285,7 @@ public: } void set_tangent_planes(const TS_container& tangent_spaces -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) , const OS_container& orthogonal_spaces #endif ) @@ -295,14 +295,14 @@ public: << " tangent spaces manually at the same time" << std::endl; std::exit(EXIT_FAILURE); #endif -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) CGAL_assertion(m_points.size() == tangent_spaces.size() && m_points.size() == orthogonal_spaces.size()); #else CGAL_assertion(m_points.size() == tangent_spaces.size()); #endif m_tangent_spaces = tangent_spaces; -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_orth_spaces = orthogonal_spaces; #endif for(std::size_t i=0; i m_are_tangent_spaces_computed; TS_container m_tangent_spaces; -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) OS_container m_orth_spaces; #endif Tr_container m_triangulations; // Contains the triangulations From f0b2722903dbd3daff1dd16d00470197975ad842 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 13:23:54 +0200 Subject: [PATCH 291/487] Added an option to perturb tangent planes --- Tangential_complex/include/CGAL/Tangential_complex.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 4d1e89e3c3a..5bae49d9a7f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -72,6 +72,7 @@ const double ALPHA = 0.3; //CJTODO: debug //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D +//#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE namespace CGAL { @@ -1687,6 +1688,10 @@ next_face: //const Point p = transl( // m_points[nn_it->first], m_translations[nn_it->first]); mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); +#ifdef CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE + mat_points(j, i) += m_random_generator.get_double( + -0.5*m_half_sparsity, 0.5*m_half_sparsity); +#endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE if (perturb) mat_points(j, i) += m_random_generator.get_double( From b78cb7ecf81897b619948a9f6e3b2713e490f0f2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 13:28:17 +0200 Subject: [PATCH 292/487] Better export for flat torus + debug code --- .../include/CGAL/Tangential_complex.h | 76 ++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5bae49d9a7f..1c65f03cec1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -69,10 +69,13 @@ //#define CGAL_FIXED_ALPHA_TC const double ALPHA = 0.3; +//static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP + //CJTODO: debug //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE +//#define BETTER_EXPORT_FOR_FLAT_TORUS namespace CGAL { @@ -2353,8 +2356,15 @@ next_face: for (int ii = 0 ; ii < N ; ++ii) { int i = 0; +#if BETTER_EXPORT_FOR_FLAT_TORUS + // For flat torus + os << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 2)) << " " + << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 3)) << " " + << 1 * CGAL::to_double(coord(p, 1)); +#else for ( ; i < num_coords ; ++i) os << CGAL::to_double(coord(p, i)) << " "; +#endif if (i == 2) os << "0"; @@ -2593,11 +2603,51 @@ next_face: } std::cerr << std::endl; }*/ + + // CJTODO TEMP DEBUG + // If co-intrinsic dimension = 1, let's compare normals + /*if (m_ambient_dim - m_intrinsic_dimension == 1) + { + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Squared_length_d k_sqlen = + m_k.squared_length_d_object(); + Vector pq = k_diff_pts( + compute_perturbed_point(q_idx), compute_perturbed_point(p_idx)); + pq = k_scaled_vec(pq, FT(1)/sqrt(k_sqlen(pq))); + FT dot_product_1 = std::abs( + k_inner_pdct(m_orth_spaces[p_idx][0], pq)); + FT dot_product_2 = std::abs( + k_inner_pdct(m_orth_spaces[q_idx][0], pq)); + csv_stream << inside_pt_indices.size() << " ; "; + csv_stream << dot_product_1 << " ; " << dot_product_2; + csv_stream << std::endl; + }*/ + // CJTODO TEMP DEBUG if (inside_pt_indices.size() > 1) { std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " << inconsistent_simplex.size() - 1 << " simplex\n"; + + // If co-intrinsic dimension = 1, let's compare normals + /*if (m_ambient_dim - m_intrinsic_dimension == 1) + { + std::cerr << "(dot product between normals = "; + std::set::const_iterator it_v = + inconsistent_simplex.begin(); + std::size_t i1 = *it_v; + ++it_v; + for ( ; it_v != inconsistent_simplex.end() ; ++it_v) + { + FT dot_products_between_normals = + k_inner_pdct(m_tangent_spaces[i1][0], m_tangent_spaces[*it_v][0]); + std::cerr << dot_products_between_normals << ", "; + //csv_stream << " ; " <= 3." << std::endl << "==========================================================" << std::endl << std::endl; @@ -3157,7 +3229,7 @@ public: std::cerr << std::endl << "==========================================================" << std::endl - << "check_correlation_between_inconsistencies_and_slivers()\n" + << "check_correlation_between_inconsistencies_and_fatness()\n" << " * Avg. volume/longest_edge^d ratio of consistent simplices: " << avg_vol_edge_ratio_consistent << " (" << num_consistent_simplices << " simplices)" << std::endl From 4e61119d0bd30c0dd6a51fe086a6a92d737a57cf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 13:30:14 +0200 Subject: [PATCH 293/487] Better generate_points_on_plane + generate_points_on_two_orthogonal_spheres_d --- .../Tangential_complex/benchmark_tc.cpp | 7 +- .../test/Tangential_complex/test_utilities.h | 78 +++++++++++++++++-- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ef920ed2f2f..81082b5cbbc 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -337,6 +337,8 @@ void make_tc(std::vector &points, //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); + //tc.check_correlation_between_inconsistencies_and_fatness(); + //=========================================================================== // Export to OFF //=========================================================================== @@ -371,6 +373,8 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", final_num_inconsistent_local_tr); + //tc.check_correlation_between_inconsistencies_and_fatness(); + //========================================================================= // Export to OFF //========================================================================= @@ -644,7 +648,8 @@ int main() } else if (input == "generate_plane") { - points = generate_points_on_plane(num_points); + points = generate_points_on_plane( + num_points, intrinsic_dim, ambient_dim); } else if (input == "generate_sphere_d") { diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 1b0d0ff4ed1..82a58c776c3 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -237,7 +237,8 @@ bool load_points_from_file( } template -std::vector generate_points_on_plane(std::size_t num_points) +std::vector generate_points_on_plane( + std::size_t num_points, int intrinsic_dim, int ambient_dim) { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; @@ -250,9 +251,14 @@ std::vector generate_points_on_plane(std::size_t num_p #endif for (std::size_t i = 0 ; i < num_points ; ) { - FT x = rng.get_double(0, 5); - FT y = rng.get_double(0, 5); - Point p = construct_point(k, x, y, FT(0)); + std::vector pt(ambient_dim, FT(0)); + for (int j = 0 ; j < intrinsic_dim ; ++j) + pt[j] = rng.get_double(-5., 5.); + /*for (int j = intrinsic_dim ; j < ambient_dim ; ++j) + pt[j] = rng.get_double(-0.01, 0.01);*/ + + Point p = k.construct_point_d_object()(ambient_dim, pt.begin(), pt.end()); + #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) ++i; @@ -424,7 +430,7 @@ std::vector generate_points_on_torus_d( pt.push_back(std::sin(alpha)); } - Point p = k.construct_point_d_object()(pt.size(), pt.begin(), pt.end()); + Point p = k.construct_point_d_object()(pt.begin(), pt.end()); #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) ++i; @@ -536,6 +542,68 @@ std::vector generate_points_on_two_spheres_d( return points; } +template +std::vector +generate_points_on_two_orthogonal_spheres_d( + std::size_t num_points, int intrinsic_dim, int ambient_dim, double radius, + double distance_between_centers, double radius_noise_percentage = 0.) +{ + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + Kernel k; + CGAL::Random rng; + CGAL::Random_points_on_sphere_d generator(dim, radius); + std::vector points; + points.reserve(num_points); + + typename Kernel::Compute_coordinate_d k_coord = + k.compute_coordinate_d_object(); + + std::vector t(dim, FT(0)); + t[0] = distance_between_centers; + Vector c1_to_c2(t.begin(), t.end()); + +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + Point p = *generator++; + if (radius_noise_percentage > 0.) + { + double radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage)/100., + (100. + radius_noise_percentage)/100.); + + typename Kernel::Point_to_vector_d k_pt_to_vec = + k.point_to_vector_d_object(); + typename Kernel::Vector_to_point_d k_vec_to_pt = + k.vector_to_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + k.scaled_vector_d_object(); + p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio)); + } + + std::vector pt1(ambient_dim); + for (int i = 0 ; i < intrinsic_dim ; ++i) + pt1[i] = k_coord(p, i); + // TODO : p2 + +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + if (sparsifier.try_to_insert_point(p)) + ++i; + if (sparsifier.try_to_insert_point(p2)) + ++i; +#else + points.push_back(p); + points.push_back(p2); + i += 2; +#endif + } + return points; +} + // Product of a 3-sphere and a circle => d = 3 / D = 5 template std::vector generate_points_on_3sphere_and_circle( From fc891eafb50c785f1d7b6a888f65741afd905945 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 15:39:49 +0200 Subject: [PATCH 294/487] CGAL_ALPHA_TC => CGAL_FIXED_ALPHA_TC --- Tangential_complex/test/Tangential_complex/aniso_TC.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp index 586c63b0bdc..147411ee2e5 100644 --- a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp +++ b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp @@ -201,7 +201,7 @@ void compute_and_set_tangent_planes(TC& tc, } tsc.push_back(CGAL::Tangential_complex_::compute_gram_schmidt_basis(ts, kerd)); -#ifdef CGAL_ALPHA_TC +#ifdef CGAL_FIXED_ALPHA_TC // compute the osc Basis os(origin); @@ -211,7 +211,7 @@ void compute_and_set_tangent_planes(TC& tc, } tc.set_tangent_planes(tsc -#ifdef CGAL_ALPHA_TC +#ifdef CGAL_FIXED_ALPHA_TC , osc #endif ); From 4fb3edce3f3f98c2ddd6c9fc0135c83268a927a9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 15:40:16 +0200 Subject: [PATCH 295/487] Add thickening vectors to Basis and take it into account in the TC Now, the dimension of the local triangulation is not always m_intrinsic_dimension. --- .../include/CGAL/Tangential_complex.h | 135 +++++++++++++----- .../include/CGAL/Tangential_complex/config.h | 6 + .../CGAL/Tangential_complex/utilities.h | 48 ++++++- 3 files changed, 149 insertions(+), 40 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 1c65f03cec1..8b0edab8d9b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -66,8 +66,6 @@ #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) -//#define CGAL_FIXED_ALPHA_TC -const double ALPHA = 0.3; //static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP @@ -102,6 +100,25 @@ template < typename Kernel, // ambiant dimension typename DimensionTag, // intrinsic dimension typename Concurrency_tag = CGAL::Parallel_tag, +#ifdef CGAL_ALPHA_TC + // For the alpha-TC, the dimension of the RT is variable + // => we need to force it to Dynamic_dimension_tag + typename Tr = Regular_triangulation + < + Regular_triangulation_euclidean_traits< + Epick_d >, + + Triangulation_data_structure + < + typename Regular_triangulation_euclidean_traits< + Epick_d >::Dimension, + Triangulation_vertex >, Vertex_data >, + Triangulation_full_cell > > + > + > +#else typename Tr = Regular_triangulation < Regular_triangulation_euclidean_traits< @@ -117,6 +134,7 @@ template < Epick_d > > > > +#endif > class Tangential_complex { @@ -1054,20 +1072,6 @@ private: if (verbose) std::cerr << "** Computing tangent tri #" << i << " **" << std::endl; //std::cerr << "***********************************************" << std::endl; - Triangulation &local_tr = - m_triangulations[i].construct_triangulation(m_intrinsic_dimension); - const Tr_traits &local_tr_traits = local_tr.geom_traits(); - Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); - - // Kernel functor & objects - typename Kernel::Squared_distance_d k_sqdist = - m_k.squared_distance_d_object(); - - // Triangulation's traits functor & objects - typename Tr_traits::Point_weight_d point_weight = - local_tr_traits.point_weight_d_object(); - typename Tr_traits::Power_center_d power_center = - local_tr_traits.power_center_d_object(); // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions @@ -1083,6 +1087,23 @@ private: m_tangent_spaces[i] = compute_tangent_space(center_pt, i); #endif } + + int triangulation_dim = local_triangulation_dim(i); + Triangulation &local_tr = + m_triangulations[i].construct_triangulation(triangulation_dim); + const Tr_traits &local_tr_traits = local_tr.geom_traits(); + Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); + + // Kernel functor & objects + typename Kernel::Squared_distance_d k_sqdist = + m_k.squared_distance_d_object(); + + // Triangulation's traits functor & objects + typename Tr_traits::Point_weight_d point_weight = + local_tr_traits.point_weight_d_object(); + typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object(); + #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { @@ -1113,8 +1134,8 @@ private: if(eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) { proj_wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(m_intrinsic_dimension, ORIGIN), - m_weights[i]); + local_tr_traits.construct_point_d_object()(triangulation_dim, ORIGIN), + m_weights[i]); } else { @@ -1175,7 +1196,7 @@ private: vh->data() = neighbor_point_idx; // Let's recompute squared_star_sphere_radius_plus_margin - if (local_tr.current_dimension() >= m_intrinsic_dimension) + if (local_tr.current_dimension() >= triangulation_dim) { squared_star_sphere_radius_plus_margin = boost::none; // Get the incident cells and look for the biggest circumsphere @@ -1781,6 +1802,13 @@ next_face: */ } + // Returns the dimension of the ith local triangulation + // This is particularly useful for the alpha-TC + int local_triangulation_dim(std::size_t i) const + { + return m_tangent_spaces[i].dimension(); + } + Point compute_perturbed_point(std::size_t pt_idx) const { #ifdef CGAL_TC_PERTURB_POSITION @@ -1834,11 +1862,19 @@ next_face: global_point = k_transl(global_point, k_scaled_vec(tsb[i], coord(p, i))); +#ifdef CGAL_ALPHA_TC + Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); + for (int i = 0 ; i < tv.size() ; ++i) + { + global_point = k_transl( + global_point, + k_scaled_vec(tv[i].vec, coord(p, m_intrinsic_dimension + i))); + } +#endif return global_point; } // Project the point in the tangent space - // The weight will be the squared distance between p and the projection of p Tr_bare_point project_point(const Point &p, const Tangent_space_basis &tsb) const { @@ -1846,19 +1882,28 @@ next_face: m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); + + Vector v = diff_points(p, tsb.origin()); std::vector coords; // Ambiant-space coords of the projected point - coords.reserve(m_intrinsic_dimension); + coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { // Local coords are given by the inner product with the vectors of tsb - Vector v = diff_points(p, tsb.origin()); FT coord = inner_pdct(v, tsb[i]); coords.push_back(coord); } - - return Tr_bare_point(m_intrinsic_dimension, coords.begin(), coords.end()); + +#ifdef CGAL_ALPHA_TC + Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); + for (int i = 0 ; i < tv.size() ; ++i) + { + FT coord = inner_pdct(v, tv[i].vec); + coords.push_back(coord); + } +#endif + return Tr_bare_point(tsb.dimension(), coords.begin(), coords.end()); } // Project the point in the tangent space @@ -1884,6 +1929,8 @@ next_face: m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); @@ -1892,24 +1939,37 @@ next_face: std::vector coords; // Ambiant-space coords of the projected point std::vector p_proj(ccci(tsb.origin()), ccci(tsb.origin(), 0)); - coords.reserve(m_intrinsic_dimension); + coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { // Local coords are given by the inner product with the vectors of tsb - FT coord = inner_pdct(v, tsb[i]); - coords.push_back(coord); + FT c = inner_pdct(v, tsb[i]); + coords.push_back(c); - // p_proj += coord * v; + // p_proj += c * v; for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += coord * tsb[i][j]; + p_proj[j] += c * coord(tsb[i], j); } + +#ifdef CGAL_ALPHA_TC + Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); + for (int i = 0 ; i < tv.size() ; ++i) + { + FT c = inner_pdct(v, tv[i].vec); + coords.push_back(c); + + // p_proj += c * v; + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += c * coord(tv[i].vec, j); + } +#endif Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); return tr_traits.construct_weighted_point_d_object() ( tr_traits.construct_point_d_object()( - m_intrinsic_dimension, coords.begin(), coords.end()), + tsb.dimension(), coords.begin(), coords.end()), w - m_k.squared_distance_d_object()(p, projected_pt) ); } @@ -1942,10 +2002,11 @@ next_face: m_triangulations[0].tr().geom_traits().difference_of_points_d_object(); std::vector s(simplex.begin(), simplex.end()); + std::size_t simplex_dim = s.size() - 1; // Compute basis Tangent_space_basis basis(m_points[s[0]]); - for (int j = 0 ; j < m_intrinsic_dimension ; ++j) + for (int j = 0 ; j < simplex_dim ; ++j) { Vector e = diff_pts( m_points[s[j+1]], m_points[s[0]]); @@ -1954,21 +2015,21 @@ next_face: basis = compute_gram_schmidt_basis(basis, m_k); // Compute the volume of the simplex: determinant - Eigen::MatrixXd m(m_intrinsic_dimension, m_intrinsic_dimension); - for (int j = 0 ; j < m_intrinsic_dimension ; ++j) + Eigen::MatrixXd m(simplex_dim, simplex_dim); + for (int j = 0 ; j < simplex_dim ; ++j) { Tr_vector v_j = tr_diff_pts( project_point(m_points[s[j+1]], basis), project_point(m_points[s[0]], basis)); - for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + for (int i = 0 ; i < simplex_dim ; ++i) m(j, i) = CGAL::to_double(coord(v_j, i)); } double volume = std::abs(m.determinant()) - / boost::math::factorial(m_intrinsic_dimension); + / boost::math::factorial(simplex_dim); // Compute the longest edge of the simplex - CGAL::Combination_enumerator combi(2, 0, m_intrinsic_dimension+1); + CGAL::Combination_enumerator combi(2, 0, simplex_dim+1); FT max_sq_length = FT(0); for ( ; !combi.finished() ; ++combi) { @@ -1978,7 +2039,7 @@ next_face: max_sq_length = sq_length; } - return volume / std::pow(CGAL::sqrt(max_sq_length), m_intrinsic_dimension); + return volume / std::pow(CGAL::sqrt(max_sq_length), simplex_dim); } // A simplex here is a list of point indices diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 19804ffaa84..150f06066c8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -30,6 +30,12 @@ # define TBB_USE_THREADING_TOOL #endif +//=========================== Alpha-TC or not? ================================ + +//#define CGAL_FIXED_ALPHA_TC +const double ALPHA = 0.3; + +#define CGAL_ALPHA_TC //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index b547125a1ef..e76fd8d3846 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -140,9 +140,10 @@ namespace Tangential_complex_ { template struct Basis { - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Vector_d Vector; - typedef typename std::vector::const_iterator const_iterator; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + typedef typename std::vector::const_iterator const_iterator; Point m_origin; //fixme should probably be (const?) ref ? std::vector m_vectors; @@ -163,6 +164,47 @@ namespace Tangential_complex_ { Basis(const Point& p, const std::vector& vectors) : m_origin(p), m_vectors(vectors) { } + +#ifdef CGAL_ALPHA_TC + // Thickening vectors... + + struct Thickening_vector + { + Thickening_vector() : alpha_minus(FT(0)), alpha_plus(FT(0)) {} + + Vector vec; + FT alpha_minus; + FT alpha_plus; + }; + typedef std::vector Thickening_vectors; + + Thickening_vectors m_thickening_vectors; + + + std::size_t num_thickening_vectors() const + { + return m_thickening_vectors.size(); + } + Thickening_vectors const& thickening_vectors() const + { + return m_thickening_vectors; + } + void add_thickening_vector(Vector const& vec, FT alpha_minus, FT alpha_plus) + { + m_thickening_vectors.push_back( + Thickening_vector(vec, alpha_minus, alpha_plus)); + } + + int dimension() const + { + return static_cast(m_vectors.size() + m_thickening_vectors.size()); + } +#else + int dimension() const + { + return static_cast(m_vectors.size()); + } +#endif }; template From 0232ae4ff8ad1d200fcb43f02765896f715e651a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 15:40:39 +0200 Subject: [PATCH 296/487] Fix warning --- Tangential_complex/test/Tangential_complex/test_utilities.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 82a58c776c3..6f90145622e 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -381,7 +381,8 @@ static void generate_uniform_points_on_torus_d( if (current_point.size() == 2*dim) { *out++ = k.construct_point_d_object()( - current_point.size(), current_point.begin(), current_point.end()); + static_cast(current_point.size()), + current_point.begin(), current_point.end()); } else { From b93ecfe222385e03d2ae0414ffd4a4a61f95348c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 16:34:52 +0200 Subject: [PATCH 297/487] Moved and fixed does_voronoi_face_and_alpha_tangent_subspace_intersect It now takes position perturbations into account --- .../include/CGAL/Tangential_complex.h | 153 ++++++++++++++++-- .../CGAL/Tangential_complex/utilities.h | 146 ----------------- 2 files changed, 142 insertions(+), 157 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8b0edab8d9b..b08de382716 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -102,7 +102,7 @@ template < typename Concurrency_tag = CGAL::Parallel_tag, #ifdef CGAL_ALPHA_TC // For the alpha-TC, the dimension of the RT is variable - // => we need to force it to Dynamic_dimension_tag + // => we need to force typename Tr = Regular_triangulation < Regular_triangulation_euclidean_traits< @@ -1349,8 +1349,7 @@ private: Amb_RT local_amb_tr(m_ambient_dim); // Insert p - Weighted_point wp = m_k.construct_weighted_point_d_object()(center_pt, - m_weights[i]); + Weighted_point wp = compute_perturbed_weighted_point(i); Amb_RT_VH center_vertex = local_amb_tr.insert(wp); center_vertex->data() = i; if (verbose) @@ -1378,12 +1377,6 @@ private: // called while other threads are perturbing the positions Weighted_point neighbor_wp = compute_perturbed_weighted_point(neighbor_point_idx); -// fixme ? -// Above seems incorrect since we later pass m_points[] to -// "does_voronoi_face_and_alpha_tangent_subspace_intersect()" and we lose -// the possible position pertubation of wp. -// Either we ignore the translations and it's neighbor_wp = points[idx]+weight -// or need to give m_translations to the voronoi intersections computations // "4*m_sq_half_sparsity" because both points can be perturbed if (squared_star_sphere_radius_plus_margin @@ -1574,8 +1567,7 @@ next_face: #endif bool does_intersect = does_voronoi_face_and_alpha_tangent_subspace_intersect( - m_points, m_weights, i, P, curr_neighbors, - m_orth_spaces[i], alpha, m_k); + i, P, curr_neighbors, m_orth_spaces[i], alpha); if (does_intersect) { star.push_back(current_DT_face); @@ -2878,6 +2870,145 @@ next_face: return inconsistencies_found; } + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_alpha_tangent_subspace_intersect( + std::size_t center_pt_index, + Indexed_point_range const& P, + Indexed_point_range_2 const& Q, + Orthogonal_space_basis const& orthogonal_subspace_basis, + FT alpha) + { + // Notations: + // Fv: Voronoi k-face + // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) + + typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); + typename Kernel::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); + typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); + + Point center_pt = compute_perturbed_point(center_pt_index); + int const ambient_dim = m_k.point_dimension_d_object()(center_pt); + + std::size_t card_P = P.size(); + std::size_t card_Q = Q.size(); + std::size_t card_OSB = orthogonal_subspace_basis.size(); + std::size_t num_couples_among_P = card_P*(card_P-1)/2; + std::size_t num_equations = + 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; + + // Linear solver + typedef CGAL::Quadratic_program Linear_program; + typedef CGAL::Quadratic_program_solution LP_solution; + + Linear_program lp(CGAL::SMALLER, false); + int current_row = 0; + + //=========== First set of equations =========== + // For points pi in P + // 2(p0 - pi).x = p0^2 - w0 - pi^2 + wi + Point const& p0 = center_pt; + FT const w0 = m_weights[center_pt_index]; + FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); + + for (typename Indexed_point_range::const_iterator it_p = P.begin(), + it_p_end = P.end() ; + it_p != it_p_end ; ++it_p) + { + Point pi; + FT wi; + compute_perturbed_weighted_point(*it_p, pi, wi); + + for (int k = 0 ; k < ambient_dim ; ++k) + lp.set_a(k, current_row, 2*(coord(p0, k) - coord(pi, k))); + + FT pi_dot_pi = scalar_pdct(pt_to_vec(pi), pt_to_vec(pi)); + lp.set_b(current_row, p0_dot_p0 - pi_dot_pi - w0 + wi); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + // CJTODO: this code might be useful for Option 1 + /*CGAL::Combination_enumerator pi_pj(2, 0, static_cast(card_P)); + for ( ; !pi_pj.finished() ; ++pi_pj) + { + Point const& pi = P[pi_pj[0]]; + FT wi = all_weights[pi_pj[0]]; + Point const& pj = P[pi_pj[1]]; + FT wj = all_weights[pi_pj[1]]; + + for (int k = 0 ; k < ambient_dim ; ++k) + { + FT a = 2*(coord(pi, k) + coord(pj, k)); + lp.set_a(k, current_row , -a); + lp.set_a(k, current_row + 1, a); + } + + FT b = scalar_pdct(pi, pi) - wi - scalar_pdct(pj, pj) + wj; + lp.set_b(current_row , -b); + lp.set_b(current_row + 1, b); + + current_row += 2; + }*/ + + //=========== Second set of equations =========== + // For each point qi in Q + // 2(qi - p0).x <= qi^2 - wi - p0^2 + w0 + for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; + it_q != it_q_end ; ++it_q) + { + Point qi; + FT wi; + compute_perturbed_weighted_point(*it_q, qi, wi); + + for (int k = 0 ; k < ambient_dim ; ++k) + lp.set_a(k, current_row, 2*(coord(qi, k) - coord(p0, k))); + + FT qi_dot_qi = scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)); + lp.set_b(current_row, qi_dot_qi - wi - p0_dot_p0 + w0); + + ++current_row; + } + + //=========== Third set of equations =========== + // For each vector bi of OSB, (x-p).bi <= alpha and >= -alpha + // p is the origin of the basis + // bi.x <= bi.p + alpha + // -bi.x <= -bi.p + alpha + for (typename Orthogonal_space_basis::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; + it_osb != it_osb_end ; ++it_osb) + { + Vector const& bi = *it_osb; + + for (int k = 0 ; k < ambient_dim ; ++k) + { + lp.set_a(k, current_row , bi[k]); + lp.set_a(k, current_row + 1, -bi[k]); + } + + Point const& basis_origin = orthogonal_subspace_basis.origin(); + FT bi_dot_p = scalar_pdct(bi, pt_to_vec(basis_origin)); + lp.set_b(current_row , bi_dot_p + alpha); + lp.set_b(current_row + 1, -bi_dot_p + alpha); + + current_row += 2; + } + + //=========== Other LP parameters =========== + lp.set_c(0, 1); // Minimize x[0] + + //=========== Solve ========================= + LP_solution solution = CGAL::solve_linear_program(lp, ET()); + bool ret = (solution.status() == CGAL::QP_OPTIMAL); + + return ret; + } + std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_OFF_simplices, bool color_inconsistencies = false, diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index e76fd8d3846..3a4b9e42609 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -263,152 +263,6 @@ namespace Tangential_complex_ { } while (std::next_permutation(booleans.begin(), booleans.end())); } - // P: dual face in Delaunay triangulation (p0, p1, ..., pn) - // Q: vertices which are common neighbors of all vertices of P - template - bool does_voronoi_face_and_alpha_tangent_subspace_intersect( - Point_range const& all_points, - Weight_range const& all_weights, - std::size_t center_pt_index, - Indexed_point_range const& P, - Indexed_point_range_2 const& Q, - Basis const& orthogonal_subspace_basis, - typename K::FT alpha, - K const& k) - { - // Notations: - // Fv: Voronoi k-face - // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) - - typedef typename K::FT FT; - typedef typename K::Point_d Point; - typedef typename K::Vector_d Vector; - - typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); - typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); - typename K::Compute_coordinate_d coord = k.compute_coordinate_d_object(); - - Point const& center_pt = all_points[center_pt_index]; - int const ambient_dim = k.point_dimension_d_object()(center_pt); - - std::size_t card_P = P.size(); - std::size_t card_Q = Q.size(); - std::size_t card_OSB = orthogonal_subspace_basis.size(); - std::size_t num_couples_among_P = card_P*(card_P-1)/2; - std::size_t num_equations = - 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; - - // Linear solver - typedef CGAL::Quadratic_program Linear_program; - typedef CGAL::Quadratic_program_solution LP_solution; - - Linear_program lp(CGAL::SMALLER, false); - int current_row = 0; - - //=========== First set of equations =========== - // For points pi in P - // 2(p0 - pi).x = p0^2 - w0 - pi^2 + wi - Point const& p0 = center_pt; - FT const w0 = all_weights[center_pt_index]; - FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); - - for (typename Indexed_point_range::const_iterator it_p = P.begin(), - it_p_end = P.end() ; - it_p != it_p_end ; ++it_p) - { - Point const& pi = all_points[*it_p]; - FT const wi = all_weights[*it_p]; - - for (int k = 0 ; k < ambient_dim ; ++k) - lp.set_a(k, current_row, 2*(coord(p0, k) - coord(pi, k))); - - FT pi_dot_pi = scalar_pdct(pt_to_vec(pi), pt_to_vec(pi)); - lp.set_b(current_row, p0_dot_p0 - pi_dot_pi - w0 + wi); - lp.set_r(current_row, CGAL::EQUAL); - - ++current_row; - } - - // CJTODO: this code might be useful for Option 1 - /*CGAL::Combination_enumerator pi_pj(2, 0, static_cast(card_P)); - for ( ; !pi_pj.finished() ; ++pi_pj) - { - Point const& pi = P[pi_pj[0]]; - FT wi = all_weights[pi_pj[0]]; - Point const& pj = P[pi_pj[1]]; - FT wj = all_weights[pi_pj[1]]; - - for (int k = 0 ; k < ambient_dim ; ++k) - { - FT a = 2*(coord(pi, k) + coord(pj, k)); - lp.set_a(k, current_row , -a); - lp.set_a(k, current_row + 1, a); - } - - FT b = scalar_pdct(pi, pi) - wi - scalar_pdct(pj, pj) + wj; - lp.set_b(current_row , -b); - lp.set_b(current_row + 1, b); - - current_row += 2; - }*/ - - //=========== Second set of equations =========== - // For each point qi in Q - // 2(qi - p0).x <= qi^2 - wi - p0^2 + w0 - for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), - it_q_end = Q.end() ; - it_q != it_q_end ; ++it_q) - { - Point const& qi = all_points[*it_q]; - FT const wi = all_weights[*it_q]; - - for (int k = 0 ; k < ambient_dim ; ++k) - lp.set_a(k, current_row, 2*(coord(qi, k) - coord(p0, k))); - - FT qi_dot_qi = scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)); - lp.set_b(current_row, qi_dot_qi - wi - p0_dot_p0 + w0); - - ++current_row; - } - - //=========== Third set of equations =========== - // For each vector bi of OSB, (x-p).bi <= alpha and >= -alpha - // p is the origin of the basis - // bi.x <= bi.p + alpha - // -bi.x <= -bi.p + alpha - for (typename Basis::const_iterator it_osb = - orthogonal_subspace_basis.begin(), - it_osb_end = orthogonal_subspace_basis.end() ; - it_osb != it_osb_end ; ++it_osb) - { - Vector const& bi = *it_osb; - - for (int k = 0 ; k < ambient_dim ; ++k) - { - lp.set_a(k, current_row , bi[k]); - lp.set_a(k, current_row + 1, -bi[k]); - } - - Point const& basis_origin = orthogonal_subspace_basis.origin(); - FT bi_dot_p = scalar_pdct(bi, pt_to_vec(basis_origin)); - lp.set_b(current_row , bi_dot_p + alpha); - lp.set_b(current_row + 1, -bi_dot_p + alpha); - - current_row += 2; - } - - //=========== Other LP parameters =========== - lp.set_c(0, 1); // Minimize x[0] - - //=========== Solve ========================= - LP_solution solution = CGAL::solve_linear_program(lp, ET()); - bool ret = (solution.status() == CGAL::QP_OPTIMAL); - - return ret; - } - } // namespace Tangential_complex_ } //namespace CGAL From 723ec9b1a97ea497974d364c6d64713d5eebcbc5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 19:19:50 +0200 Subject: [PATCH 298/487] Missing constructor + improve code --- Tangential_complex/include/CGAL/Tangential_complex.h | 7 +++---- .../include/CGAL/Tangential_complex/utilities.h | 5 ++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b08de382716..c30802731df 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1097,6 +1097,7 @@ private: // Kernel functor & objects typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); + typename Kernel::Equal_d k_eq = m_k.equal_d_object(); // Triangulation's traits functor & objects typename Tr_traits::Point_weight_d point_weight = @@ -1128,10 +1129,8 @@ private: //*************************************************** // Insert p - typename Kernel::Equal_d eq = m_k.equal_d_object(); - Tr_point proj_wp; - if(eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) + if(k_eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) { proj_wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(triangulation_dim, ORIGIN), @@ -1343,7 +1342,7 @@ private: //*************************************************** #ifdef CGAL_TC_PROFILING - Wall_clock_timer t_star; + Wall_clock_timer t_star; #endif Amb_RT local_amb_tr(m_ambient_dim); diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 3a4b9e42609..f0a8e7b99c4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -170,7 +170,10 @@ namespace Tangential_complex_ { struct Thickening_vector { - Thickening_vector() : alpha_minus(FT(0)), alpha_plus(FT(0)) {} + Thickening_vector() + : alpha_minus(FT(0)), alpha_plus(FT(0)) {} + Thickening_vector(Vector const& v, FT am, FT ap) + : vec(v), alpha_minus(am), alpha_plus(ap) {} Vector vec; FT alpha_minus; From 758482934a657b3346e65c8063f3c6709251155f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 17 Jun 2015 19:05:13 +0200 Subject: [PATCH 299/487] Take the "thickening vectors" into account when computing the TC Replacement of the previous fixed-alpha TC code by a version using the "thickening vectors" (for now, the alphas associated to a thickening vector have the same hard-coded values) --- .../include/CGAL/Tangential_complex.h | 508 +++++++++--------- .../include/CGAL/Tangential_complex/config.h | 5 +- 2 files changed, 245 insertions(+), 268 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c30802731df..69b470748f5 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -266,7 +266,7 @@ public: , m_points_ds(m_points) , m_are_tangent_spaces_computed(m_points.size(), false) , m_tangent_spaces(m_points.size(), Tangent_space_basis()) -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) #endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM @@ -307,7 +307,7 @@ public: } void set_tangent_planes(const TS_container& tangent_spaces -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS , const OS_container& orthogonal_spaces #endif ) @@ -317,14 +317,14 @@ public: << " tangent spaces manually at the same time" << std::endl; std::exit(EXIT_FAILURE); #endif -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS CGAL_assertion(m_points.size() == tangent_spaces.size() && m_points.size() == orthogonal_spaces.size()); #else CGAL_assertion(m_points.size() == tangent_spaces.size()); #endif m_tangent_spaces = tangent_spaces; -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS m_orth_spaces = orthogonal_spaces; #endif for(std::size_t i=0; i& r ) const { for( size_t i = r.begin() ; i != r.end() ; ++i) - { -#ifdef CGAL_FIXED_ALPHA_TC - m_tc.compute_alpha_tangent_triangulation(i, ALPHA); -#else m_tc.compute_tangent_triangulation(i); -#endif - } } }; #endif // CGAL_LINKED_WITH_TBB @@ -1076,17 +1060,34 @@ private: // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions const Point center_pt = compute_perturbed_point(i); + Tangent_space_basis &tsb = m_tangent_spaces[i]; // Estimate the tangent space if (!m_are_tangent_spaces_computed[i]) { -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = - compute_tangent_space(center_pt, i, true/*normalize*/, &m_orth_spaces[i]); +#ifdef CGAL_TC_EXPORT_NORMALS + tsb = compute_tangent_space(center_pt, i, true/*normalize*/, &m_orth_spaces[i]); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt, i); + tsb = compute_tangent_space(center_pt, i); #endif } +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + else if (m_perturb_tangent_space[i]) + { +#ifdef CGAL_TC_EXPORT_NORMALS + tsb = compute_tangent_space(center_pt, i, + true /*normalize_basis*/, + &m_orth_spaces[i], + true /*perturb*/); +#else + tsb = compute_tangent_space(center_pt, i, + true /*normalize_basis*/, + NULL /*ortho basis*/, + true /*perturb*/); +#endif + m_perturb_tangent_space[i] = false; + } +#endif int triangulation_dim = local_triangulation_dim(i); Triangulation &local_tr = @@ -1105,23 +1106,6 @@ private: typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object(); -#ifdef CGAL_TC_PERTURB_TANGENT_SPACE - else if (m_perturb_tangent_space[i]) - { -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = compute_tangent_space(center_pt, i, - true /*normalize_basis*/, - &m_orth_spaces[i], - true /*perturb*/); -#else - m_tangent_spaces[i] = compute_tangent_space(center_pt, i, - true /*normalize_basis*/, - NULL /*ortho basis*/, - true /*perturb*/); -#endif - m_perturb_tangent_space[i] = false; - } -#endif //*************************************************** // Build a minimal triangulation in the tangent space @@ -1130,7 +1114,7 @@ private: // Insert p Tr_point proj_wp; - if(k_eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) + if(k_eq(compute_perturbed_point(i), tsb.origin())) { proj_wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(triangulation_dim, ORIGIN), @@ -1139,8 +1123,7 @@ private: else { const Weighted_point& wp = compute_perturbed_weighted_point(i); - proj_wp = project_point_and_compute_weight(wp, m_tangent_spaces[i], - local_tr_traits); + proj_wp = project_point_and_compute_weight(wp, tsb, local_tr_traits); } center_vertex = local_tr.insert(proj_wp); @@ -1182,7 +1165,7 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, neighbor_weight, m_tangent_spaces[i], + neighbor_pt, neighbor_weight, tsb, local_tr_traits); Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); @@ -1251,11 +1234,26 @@ private: } } +#ifdef CGAL_ALPHA_TC + if (tsb.num_thickening_vectors() == 0) + update_star__no_thickening_vectors(i); + else + update_star__with_thickening_vector(i); +#else + update_star__no_thickening_vectors(i); +#endif + } + + // Updates m_stars[i] directly from m_triangulations[i] + void update_star__no_thickening_vectors(std::size_t i) + { //*************************************************** // Update the associated star (in m_stars) //*************************************************** Star &star = m_stars[i]; star.clear(); + Triangulation &local_tr = m_triangulations[i].tr(); + Tr_vertex_handle center_vertex = m_triangulations[i].center_vertex(); int cur_dim_plus_1 = local_tr.current_dimension() + 1; std::vector incident_cells; @@ -1288,214 +1286,64 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } -#ifdef CGAL_FIXED_ALPHA_TC - void compute_alpha_tangent_triangulation(std::size_t i, FT alpha, - bool verbose = false) +#ifdef CGAL_ALPHA_TC + void update_star__with_thickening_vector(std::size_t i) { - if (verbose) - std::cerr << "** Computing alpha tangent tri #" - << i << " **" << std::endl; - - typedef Regular_triangulation_euclidean_traits Amb_RT_Traits; - typedef Regular_triangulation< - Amb_RT_Traits, - Triangulation_data_structure< - typename Amb_RT_Traits::Dimension, - Triangulation_vertex - > > Amb_RT; - typedef typename Amb_RT::Weighted_point Amb_RT_Point; - typedef typename Amb_RT::Vertex_handle Amb_RT_VH; - typedef typename Amb_RT::Full_cell_handle Amb_RT_FCH; - //typedef typename Amb_RT::Finite_full_cell_const_iterator Amb_FFC_it; - - typename Kernel::Point_drop_weight_d k_drop_w = - m_k.point_drop_weight_d_object(); - typename Kernel::Squared_distance_d k_sqdist = - m_k.squared_distance_d_object(); - typename Kernel::Point_weight_d k_point_weight = - m_k.point_weight_d_object(); - typename Kernel::Power_center_d k_power_center = - m_k.power_center_d_object(); - - // No need to lock the mutex here since this will not be called while - // other threads are perturbing the positions - const Point ¢er_pt = m_points[i]; - - // Estimate the tangent space - if (!m_are_tangent_spaces_computed[i]) - { - m_tangent_spaces[i] = - compute_tangent_space(center_pt, i, true /*normalize*/, &m_orth_spaces[i]); - } -#ifdef CGAL_TC_PERTURB_TANGENT_SPACE - else if (m_perturb_tangent_space[i]) - { - m_tangent_spaces[i] = - compute_tangent_space(center_pt, i, true, &m_orth_spaces[i], true); - m_perturb_tangent_space[i] = false; - } -#endif - - //*************************************************** - // Build a minimal triangulation in the tangent space - // (we only need the star of p in the AMBIENT triangulation) - //*************************************************** - -#ifdef CGAL_TC_PROFILING - Wall_clock_timer t_star; -#endif - - Amb_RT local_amb_tr(m_ambient_dim); - - // Insert p - Weighted_point wp = compute_perturbed_weighted_point(i); - Amb_RT_VH center_vertex = local_amb_tr.insert(wp); - center_vertex->data() = i; - if (verbose) - std::cerr << "* Inserted point #" << i << std::endl; - - INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); - - // While building the local triangulation, we keep the radius - // of the sphere "star sphere" centered at "center_vertex" - // and which contains all the - // circumspheres of the star of "center_vertex" - boost::optional squared_star_sphere_radius_plus_margin; - - // Insert points until we find a point which is outside "star shere" - for (INS_iterator nn_it = ins_range.begin() ; - nn_it != ins_range.end() ; - ++nn_it) - { - std::size_t neighbor_point_idx = nn_it->first; - - // ith point = p, which is already inserted - if (neighbor_point_idx != i) - { - // No need to lock the Mutex_for_perturb here since this will not be - // called while other threads are perturbing the positions - Weighted_point neighbor_wp = - compute_perturbed_weighted_point(neighbor_point_idx); - - // "4*m_sq_half_sparsity" because both points can be perturbed - if (squared_star_sphere_radius_plus_margin - && k_sqdist(center_pt, k_drop_w(neighbor_wp)) - > *squared_star_sphere_radius_plus_margin) - break; - - Amb_RT_VH vh = local_amb_tr.insert_if_in_star(neighbor_wp, center_vertex); - //Amb_RT_VH vh = local_amb_tr.insert(neighbor_wp); - if (vh != Amb_RT_VH()) - { - if (verbose) - std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; - - vh->data() = neighbor_point_idx; - - // Let's recompute squared_star_sphere_radius_plus_margin - if (local_amb_tr.current_dimension() == m_ambient_dim) - { - squared_star_sphere_radius_plus_margin = boost::none; - // Get the incident cells and look for the biggest circumsphere - std::vector incident_cells; - local_amb_tr.incident_full_cells( - center_vertex, - std::back_inserter(incident_cells)); - for (typename std::vector::iterator cit = - incident_cells.begin(); cit != incident_cells.end(); ++cit) - { - Amb_RT_FCH cell = *cit; - if (local_amb_tr.is_infinite(cell)) - { - squared_star_sphere_radius_plus_margin = boost::none; - break; - } - else - { - Amb_RT_Point c = k_power_center( - boost::make_transform_iterator( - cell->vertices_begin(), - vertex_handle_to_point), - boost::make_transform_iterator( - cell->vertices_end(), - vertex_handle_to_point)); - - FT sq_power_sphere_diam = 4*k_point_weight(c); - - if (!squared_star_sphere_radius_plus_margin - || sq_power_sphere_diam > - *squared_star_sphere_radius_plus_margin) - { - squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; - } - } - } - - // Let's add the margin, now - // The value depends on whether we perturb weight or position - if (squared_star_sphere_radius_plus_margin) - { -#ifdef CGAL_TC_PERTURB_WEIGHT - squared_star_sphere_radius_plus_margin = - *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; -#else - squared_star_sphere_radius_plus_margin = CGAL::square( - CGAL::sqrt(*squared_star_sphere_radius_plus_margin) - + 2*m_half_sparsity); -#endif - } - } - } - } - } - //*************************************************** // Parse the faces of the star and add the ones that are in the // restriction to alpha-Tp // Update the associated star (in m_stars) //*************************************************** + + int triangulation_dim = local_triangulation_dim(i); + Triangulation &local_tr = m_triangulations[i].tr(); + Tr_traits const& local_tr_traits = local_tr.geom_traits(); + Tr_vertex_handle center_vertex = m_triangulations[i].center_vertex(); + Tangent_space_basis const& tsb = m_tangent_spaces[i]; + Star &star = m_stars[i]; star.clear(); - int cur_dim_plus_1 = m_ambient_dim + 1; + int cur_dim_plus_1 = triangulation_dim + 1; - std::vector incident_cells; - local_amb_tr.incident_full_cells( + std::vector incident_cells; + local_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); - typedef std::set DT_face; // DT face without center vertex (i) - typedef std::set Neighbor_vertices; + typedef std::set DT_face; // DT face without center vertex (i) + typedef std::set Neighbor_vertices; typedef std::map DT_faces_and_neighbors; - // Maps that associate a k-face and the list of its neighbor points - // (i.e. there are k+1-cofaces that contain these points) - // N.B.: each k-face contains 'i', so 'i' is not stored in the faces - // faces_and_neighbors[0] => dim 1, faces_and_neighbors[1] => dim 2 + // Maps that associate a m-face F and the points of its m+1-cofaces + // (except the points of F). Those points are called its "neighbors". + // N.B.: each m-face contains 'i', so 'i' is not stored in the faces + // N.B.2: faces_and_neighbors[0] => dim 1, faces_and_neighbors[1] => dim 2 std::vector faces_and_neighbors; - faces_and_neighbors.resize(m_ambient_dim); + faces_and_neighbors.resize(triangulation_dim); // Fill faces_and_neighbors - // Let's first take care of the D-faces - typename std::vector::const_iterator it_c = incident_cells.begin(); - typename std::vector::const_iterator it_c_end = incident_cells.end(); + // Let's first take care of the maximal simplices (dim = triangulation_dim) + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end = incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { DT_face face; - // CJTODO: use (*it_c)->vertices_begin(), etc. for (int j = 0 ; j < cur_dim_plus_1 ; ++j) { - std::size_t index = (*it_c)->vertex(j)->data(); - if (index == std::numeric_limits::max()) + Tr_vertex_handle vh = (*it_c)->vertex(j); + // Skip infinite simplices + if (vh == local_tr.infinite_vertex()) goto next_face; - if (index != i) - face.insert(index); + if (vh->data() != i) + face.insert(vh); } - faces_and_neighbors[m_ambient_dim-1][face] = Neighbor_vertices(); + // No co-faces => no neighbors + faces_and_neighbors[triangulation_dim-1][face] = Neighbor_vertices(); next_face: ; } - // Then the D-k-faces... - int current_dim = m_ambient_dim - 1; + // Then the D-m-faces... + int current_dim = triangulation_dim - 1; while (current_dim > 0) { // Let's fill faces_and_neighbors[current_dim-1] @@ -1504,21 +1352,21 @@ next_face: faces_and_neighbors[current_dim-1]; typedef DT_faces_and_neighbors::const_iterator FaN_it; - // Parse k+1-faces + // Parse m+1-faces for (FaN_it it_k_p1_face = faces_and_neighbors[current_dim].begin(), it_k_p1_face_end = faces_and_neighbors[current_dim].end() ; it_k_p1_face != it_k_p1_face_end ; ++it_k_p1_face) { DT_face const& k_p1_face = it_k_p1_face->first; - // Add each k faces to cur_faces_and_nghb + // Add each m-face to cur_faces_and_nghb std::size_t n = current_dim + 1; // Not +2 since 'i' is not stored std::vector booleans(n, false); std::fill(booleans.begin() + 1, booleans.end(), true); do { DT_face k_face; - std::size_t remaining_vertex; + Tr_vertex_handle remaining_vertex; DT_face::const_iterator it_v = k_p1_face.begin(); for (std::size_t i = 0 ; i < n ; ++i, ++it_v) { @@ -1537,7 +1385,8 @@ next_face: // For each face V of Voronoi_cell(P[i]) - dim 0 to dim D-1 // I.e. For each DT face F of the star - dim D to dim 1 - current_dim = m_ambient_dim; + // Test if V intersects the thickened tangent space + current_dim = triangulation_dim; while (current_dim > 0) { // Remember: faces_and_neighbors[current_dim-1] stores @@ -1557,19 +1406,28 @@ next_face: == current_dim); // P: list of current_DT_face points (including 'i') - std::vector P( + std::vector P( current_DT_face.begin(), current_DT_face.end()); - P.push_back(i); + P.push_back(center_vertex); -#ifdef CGAL_TC_PROFILING - Wall_clock_timer t_inters; -#endif bool does_intersect = - does_voronoi_face_and_alpha_tangent_subspace_intersect( - i, P, curr_neighbors, m_orth_spaces[i], alpha); + does_voronoi_face_and_tangent_subspace_intersect( + triangulation_dim, + center_vertex, + P, + curr_neighbors, + tsb, + local_tr_traits); if (does_intersect) { - star.push_back(current_DT_face); + // Get the indices of the face's points + Incident_simplex face; + DT_face::const_iterator it_vh = current_DT_face.begin(); + DT_face::const_iterator it_vh_end = current_DT_face.end(); + for ( ; it_vh != it_vh_end ; ++it_vh) + face.insert((*it_vh)->data()); + + star.push_back(face); // Clear all subfaces of current_DT_face from the maps for (int dim = current_dim - 1 ; dim > 0 ; --dim) @@ -1596,17 +1454,9 @@ next_face: --current_dim; } - - // CJTODO DEBUG - //std::cerr << "\nChecking topology and geometry..." - // << (local_amb_tr.is_valid(true) ? "OK.\n" : "Error.\n"); - // DEBUG: output the local mesh into an OFF file - //std::stringstream sstr; - //sstr << "data/local_tri_" << i << ".off"; - //std::ofstream off_stream_tr(sstr.str()); - //CGAL::export_triangulation_to_off(off_stream_tr, local_amb_tr); } -#endif // CGAL_FIXED_ALPHA_TC +#endif //CGAL_ALPHA_TC + Tangent_space_basis compute_tangent_space( const Point &p @@ -1765,6 +1615,19 @@ next_face: } } } +#if defined(CGAL_ALPHA_TC) && defined(CGAL_USE_A_FIXED_ALPHA) + // Add the orthogonal vectors as "thickening vectors" + for (int j = m_ambient_dim - m_intrinsic_dimension - 1 ; + j >= 0 ; + --j) + { + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); + tsb.add_thickening_vector( + normalize_vector(v, m_k), -CGAL_TC_ALPHA_VALUE, CGAL_TC_ALPHA_VALUE); + } +#endif m_are_tangent_spaces_computed[i] = true; @@ -2868,16 +2731,135 @@ next_face: return inconsistencies_found; } + + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_tangent_subspace_intersect( + int points_dim, + Tr_vertex_handle center_vh, + VH_range_a const& P, + VH_range_b const& Q, + Tangent_space_basis const& tsb, + const Tr_traits &tr_traits) const + { + // Notations: + // Fv: Voronoi k-face + // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) + + typename Tr_traits::Point_drop_weight_d drop_w = + tr_traits.point_drop_weight_d_object(); + typename Tr_traits::Point_weight_d point_weight = + tr_traits.point_weight_d_object(); + typename Tr_traits::Scalar_product_d scalar_pdct = + tr_traits.scalar_product_d_object(); + typename Tr_traits::Point_to_vector_d pt_to_vec = + tr_traits.point_to_vector_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + tr_traits.compute_coordinate_d_object(); + + typename Kernel::Compute_coordinate_d k_coord = + m_k.compute_coordinate_d_object(); + + std::size_t card_P = P.size(); + std::size_t card_Q = Q.size(); + + // Linear solver + typedef CGAL::Quadratic_program Linear_program; + typedef CGAL::Quadratic_program_solution LP_solution; + + Linear_program lp(CGAL::SMALLER, false); + int current_row = 0; + + //=========== First set of equations =========== + // For points pi in P + // 2(p0 - pi).x = p0^2 - wght(p0) - pi^2 + wght(pi) + Tr_point const& p0 = center_vh->point(); + FT const w0 = point_weight(p0); + FT p0_dot_p0 = scalar_pdct(pt_to_vec(drop_w(p0)), pt_to_vec(drop_w(p0))); + + for (typename VH_range_a::const_iterator it_vh = P.begin(), + it_vh_end = P.end() ; + it_vh != it_vh_end ; ++it_vh) + { + Tr_point const& pi = (*it_vh)->point(); + FT const wi = point_weight(pi); + + for (int k = 0 ; k < points_dim ; ++k) + lp.set_a(k, current_row, 2*(coord(p0, k) - coord(pi, k))); + + FT pi_dot_pi = scalar_pdct(pt_to_vec(drop_w(pi)), pt_to_vec(drop_w(pi))); + lp.set_b(current_row, p0_dot_p0 - pi_dot_pi - w0 + wi); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + //=========== Second set of equations =========== + // For each point qi in Q + // 2(qi - p0).x <= qi^2 - wght(pi) - p0^2 + wght(p0) + for (typename VH_range_b::const_iterator it_vh = Q.begin(), + it_vh_end = Q.end() ; + it_vh != it_vh_end ; ++it_vh) + { + Tr_point const& qi = (*it_vh)->point(); + FT const wi = point_weight(qi); + + for (int k = 0 ; k < points_dim ; ++k) + lp.set_a(k, current_row, 2*(coord(qi, k) - coord(p0, k))); + + FT qi_dot_qi = scalar_pdct(pt_to_vec(drop_w(qi)), pt_to_vec(drop_w(qi))); + lp.set_b(current_row, qi_dot_qi - wi - p0_dot_p0 + w0); + + ++current_row; + } + + //=========== Third set of equations =========== + // For each thickening vector bj of TSB, + // x.bj <= alpha_plus and >= alpha_minus + // where bj is in the TSB => bj = (0..., 1..., 0) (1 is at the ith position) + // x.bj <= alpha_plus + // -x.bj <= -alpha_minus + std::size_t j = points_dim - tsb.num_thickening_vectors(); + for (Tangent_space_basis::Thickening_vectors::const_iterator + it_tv = tsb.thickening_vectors().begin(), + it_tv_end = tsb.thickening_vectors().end() ; + it_tv != it_tv_end ; ++it_tv) + { + Tangent_space_basis::Thickening_vector const& bj = *it_tv; + + for (int k = 0 ; k < points_dim ; ++k) + { + lp.set_a(k, current_row , (j == k ? 1. : 0.)); + lp.set_a(k, current_row + 1, (j == k ? -1. : 0.)); + } + + lp.set_b(current_row , bj.alpha_plus); + lp.set_b(current_row + 1, -bj.alpha_minus); + + current_row += 2; + ++j; + } + + //=========== Other LP parameters =========== + lp.set_c(0, 1); // Minimize x[0] + + //=========== Solve ========================= + LP_solution solution = CGAL::solve_linear_program(lp, ET()); + bool ret = (solution.status() == CGAL::QP_OPTIMAL); + + return ret; + } // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template + template bool does_voronoi_face_and_alpha_tangent_subspace_intersect( std::size_t center_pt_index, - Indexed_point_range const& P, - Indexed_point_range_2 const& Q, + Indexed_point_range_a const& P, + Indexed_point_range_b const& Q, Orthogonal_space_basis const& orthogonal_subspace_basis, - FT alpha) + FT alpha) const { // Notations: // Fv: Voronoi k-face @@ -2892,10 +2874,6 @@ next_face: std::size_t card_P = P.size(); std::size_t card_Q = Q.size(); - std::size_t card_OSB = orthogonal_subspace_basis.size(); - std::size_t num_couples_among_P = card_P*(card_P-1)/2; - std::size_t num_equations = - 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; // Linear solver typedef CGAL::Quadratic_program Linear_program; @@ -2911,8 +2889,8 @@ next_face: FT const w0 = m_weights[center_pt_index]; FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); - for (typename Indexed_point_range::const_iterator it_p = P.begin(), - it_p_end = P.end() ; + for (typename Indexed_point_range_a::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { Point pi; @@ -2955,7 +2933,7 @@ next_face: //=========== Second set of equations =========== // For each point qi in Q // 2(qi - p0).x <= qi^2 - wi - p0^2 + w0 - for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), + for (typename Indexed_point_range_b::const_iterator it_q = Q.begin(), it_q_end = Q.end() ; it_q != it_q_end ; ++it_q) { @@ -2977,17 +2955,17 @@ next_face: // p is the origin of the basis // bi.x <= bi.p + alpha // -bi.x <= -bi.p + alpha - for (typename Orthogonal_space_basis::const_iterator it_osb = - orthogonal_subspace_basis.begin(), - it_osb_end = orthogonal_subspace_basis.end() ; + for (Orthogonal_space_basis::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; it_osb != it_osb_end ; ++it_osb) { Vector const& bi = *it_osb; for (int k = 0 ; k < ambient_dim ; ++k) { - lp.set_a(k, current_row , bi[k]); - lp.set_a(k, current_row + 1, -bi[k]); + lp.set_a(k, current_row , coord(bi, k)); + lp.set_a(k, current_row + 1, -coord(bi, k)); } Point const& basis_origin = orthogonal_subspace_basis.origin(); @@ -3456,7 +3434,7 @@ private: Points_ds m_points_ds; std::vector m_are_tangent_spaces_computed; TS_container m_tangent_spaces; -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS OS_container m_orth_spaces; #endif Tr_container m_triangulations; // Contains the triangulations diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 150f06066c8..5ada1b8bbfa 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -32,10 +32,9 @@ //=========================== Alpha-TC or not? ================================ -//#define CGAL_FIXED_ALPHA_TC -const double ALPHA = 0.3; - #define CGAL_ALPHA_TC + #define CGAL_USE_A_FIXED_ALPHA + const double CGAL_TC_ALPHA_VALUE = 0.3; //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING From c6b1e4c7cd873de60f41265b1f6be33146914fdf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 19 Jun 2015 17:19:46 +0200 Subject: [PATCH 300/487] Function to compute the intersection between a Voronoi cell and a tangent plane Returns any point of the intersection --- .../include/CGAL/Tangential_complex.h | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 69b470748f5..ed40b96adcb 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -2735,7 +2735,8 @@ next_face: // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P template - bool does_voronoi_face_and_tangent_subspace_intersect( + CGAL::Quadratic_program_solution + compute_voronoi_face_and_tangent_subspace_LP_problem( int points_dim, Tr_vertex_handle center_vh, VH_range_a const& P, @@ -2846,7 +2847,59 @@ next_face: //=========== Solve ========================= LP_solution solution = CGAL::solve_linear_program(lp, ET()); - bool ret = (solution.status() == CGAL::QP_OPTIMAL); + return solution; + } + + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_tangent_subspace_intersect( + int points_dim, + Tr_vertex_handle center_vh, + VH_range_a const& P, + VH_range_b const& Q, + Tangent_space_basis const& tsb, + const Tr_traits &tr_traits) const + { + return compute_voronoi_face_and_tangent_subspace_LP_problem( + points_dim, center_vh, P, Q, tsb, tr_traits).status() == CGAL::QP_OPTIMAL; + } + + // Returns any point of intersection + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + boost::optional compute_voronoi_face_and_tangent_subspace_intersection( + int points_dim, + Tr_vertex_handle center_vh, + VH_range_a const& P, + VH_range_b const& Q, + Tangent_space_basis const& tsb, + const Tr_traits &tr_traits) const + { + typedef CGAL::Quadratic_program_solution LP_solution; + + LP_solution sol = compute_voronoi_face_and_tangent_subspace_LP_problem( + points_dim, center_vh, P, Q, tsb, tr_traits); + + boost::optional ret; + if (sol.status() == CGAL::QP_OPTIMAL) + { + std::vector p; + p.reserve(points_dim); + for (LP_solution::Variable_value_iterator + it_v = sol.variable_values_begin(), + it_v_end = sol.variable_values_end() ; + it_v != it_v_end ; ++it_v) + { + p.push_back(to_double(*it_v)); + } + ret = m_k.construct_point_d_object()(points_dim, p.begin(), p.end()); + } + else + { + ret = boost::none; + } return ret; } From 0332d2c7eea386394f9c12ec3f6226336540e9bb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 10:36:22 +0200 Subject: [PATCH 301/487] Param center_vertex was useless + added function... ... compute_aff_of_voronoi_face_and_tangent_subspace_intersection --- .../include/CGAL/Tangential_complex.h | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ed40b96adcb..b05fba5b9f9 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1412,8 +1412,7 @@ next_face: bool does_intersect = does_voronoi_face_and_tangent_subspace_intersect( - triangulation_dim, - center_vertex, + triangulation_dim, P, curr_neighbors, tsb, @@ -2738,7 +2737,6 @@ next_face: CGAL::Quadratic_program_solution compute_voronoi_face_and_tangent_subspace_LP_problem( int points_dim, - Tr_vertex_handle center_vh, VH_range_a const& P, VH_range_b const& Q, Tangent_space_basis const& tsb, @@ -2775,12 +2773,12 @@ next_face: //=========== First set of equations =========== // For points pi in P // 2(p0 - pi).x = p0^2 - wght(p0) - pi^2 + wght(pi) - Tr_point const& p0 = center_vh->point(); + typename VH_range_a::const_iterator it_vh = P.begin(); + Tr_point const& p0 = (*it_vh)->point(); FT const w0 = point_weight(p0); FT p0_dot_p0 = scalar_pdct(pt_to_vec(drop_w(p0)), pt_to_vec(drop_w(p0))); - - for (typename VH_range_a::const_iterator it_vh = P.begin(), - it_vh_end = P.end() ; + ++it_vh; + for (typename VH_range_a::const_iterator it_vh_end = P.end() ; it_vh != it_vh_end ; ++it_vh) { Tr_point const& pi = (*it_vh)->point(); @@ -2855,23 +2853,38 @@ next_face: template bool does_voronoi_face_and_tangent_subspace_intersect( int points_dim, - Tr_vertex_handle center_vh, VH_range_a const& P, VH_range_b const& Q, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { return compute_voronoi_face_and_tangent_subspace_LP_problem( - points_dim, center_vh, P, Q, tsb, tr_traits).status() == CGAL::QP_OPTIMAL; + points_dim, P, Q, tsb, tr_traits).status() == CGAL::QP_OPTIMAL; } - // Returns any point of intersection + // Returns any point of the intersection between aff(voronoi_cell) and a + // tangent space. + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + template + boost::optional + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + int points_dim, + VH_range_a const& P, + Tangent_space_basis const& tsb, + const Tr_traits &tr_traits) const + { + // As we're only interested by aff(v), Q is empty + return compute_voronoi_face_and_tangent_subspace_intersection( + points_dim, P, std::vector(), tsb, tr_traits); + } + + // Returns any point of the intersection between a Voronoi cell and a + // tangent space. // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P template boost::optional compute_voronoi_face_and_tangent_subspace_intersection( int points_dim, - Tr_vertex_handle center_vh, VH_range_a const& P, VH_range_b const& Q, Tangent_space_basis const& tsb, From 6e44497e856a78f998170aae66dec68c9e516c51 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 11:24:51 +0200 Subject: [PATCH 302/487] Simplified some loops --- .../include/CGAL/Tangential_complex.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b05fba5b9f9..6d8f3369a26 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -618,10 +618,8 @@ public: { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { // For each cell Star::const_iterator it_inc_simplex = m_stars[idx].begin(); @@ -668,10 +666,8 @@ public: { int max_dim = -1; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { // For each cell of the star Star::const_iterator it_inc_simplex = m_stars[idx].begin(); @@ -814,10 +810,8 @@ public: { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { // We build a SC along the way in case it's inconsistent Simplicial_complex sc; @@ -3422,10 +3416,8 @@ public: double sum_vol_edge_ratio_consistent = 0.; std::size_t num_inconsistent_simplices = 0; double sum_vol_edge_ratio_inconsistent = 0.; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { // For each cell Star::const_iterator it_inc_simplex = m_stars[idx].begin(); From 341f17a49cdc6866f250d31760e4e27468977b57 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 18:24:47 +0200 Subject: [PATCH 303/487] First step of solve_inconsistencies_using_adaptive_alpha_TC: priority queue --- .../Tangential_complex/benchmark_tc.cpp | 3 +- .../include/CGAL/Tangential_complex.h | 292 +++++++++++++++--- 2 files changed, 253 insertions(+), 42 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 81082b5cbbc..1545d2e20af 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -405,7 +405,8 @@ void make_tc(std::vector &points, //========================================================================= t.reset(); // Try to solve the remaining inconstencies - tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + //tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + tc.solve_inconsistencies_using_adaptive_alpha_TC(); fix2_time = t.elapsed(); t.reset(); max_dim = tc.export_TC(complex, false); /*std::set > not_delaunay_simplices; diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6d8f3369a26..6b2a27e3769 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -213,6 +213,34 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; + class Simplex_and_alpha + { + public: + Simplex_and_alpha() {} + Simplex_and_alpha( + std::size_t center_point_index, + std::set const& simplex, // including "center_point_index" + FT squared_alpha, + Vector const& thickening_vector) + : m_center_point_index(center_point_index), + m_simplex(simplex), + m_squared_alpha(squared_alpha), + m_thickening_vector(thickening_vector) + {} + + // For the priority queue + bool operator>(Simplex_and_alpha const& other) const + { + return m_squared_alpha > other.m_squared_alpha; + } + + private: + std::size_t m_center_point_index; // P + std::set m_simplex; // Missing simplex (includes P) + FT m_squared_alpha; + Vector m_thickening_vector; // (P, Cq) + }; + public: typedef typename std::vector TS_container; typedef typename std::vector OS_container; @@ -726,6 +754,92 @@ public: << 100. * stats_after.second / stats_after.first << "%" << std::endl; } + + void solve_inconsistencies_using_adaptive_alpha_TC() + { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif + +#ifdef CGAL_TC_VERBOSE + std::cerr << "Fixing inconsistencies using adaptive alpha TC..." << std::endl; +#endif + + // Kernel/traits functors + typename Kernel::Difference_of_points_d k_diff_points = + m_k.difference_of_points_d_object(); + typename Kernel::Squared_length_d k_sqlen = + m_k.squared_length_d_object(); + typename Tr_traits::Construct_weighted_point_d constr_wp = + m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); + + //------------------------------------------------------------------------- + //1. Fill priority queue + //------------------------------------------------------------------------- + typedef std::priority_queue, + std::greater > AATC_pq; + + AATC_pq pqueue; + + // For each triangulation + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) + { + // For each cell + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + Incident_simplex const& s = *it_inc_simplex; + + // Don't check infinite cells + if (*s.rbegin() == std::numeric_limits::max()) + continue; + + // P: points whose star does not contain "s" + std::vector P; + is_simplex_consistent(idx, s, std::back_inserter(P), true); + + if (!P.empty()) + { + Triangulation const& q_tr = m_triangulations[idx].tr(); + std::set full_simplex = s; + full_simplex.insert(idx); + for (std::vector::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) + { + // star(p) does not contain "s" + std::size_t const& p = *it_p; + + Tr_bare_point intersection = + *compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + q_tr.current_dimension(), + project_points_and_compute_weights( + full_simplex, m_tangent_spaces[idx], q_tr.geom_traits()), + m_tangent_spaces[idx], + q_tr.geom_traits()); + + // The following computations are done in the Euclidian space + Point inters_global = unproject_point( + constr_wp(intersection, 0), m_tangent_spaces[idx], + q_tr.geom_traits()); + Vector thickening_v = k_diff_points(inters_global, m_points[p]); + FT squared_alpha = k_sqlen(thickening_v); + + pqueue.push(Simplex_and_alpha( + p, full_simplex, squared_alpha, thickening_v)); + } + } + } + } + + // CJTODO: the rest + +#ifdef CGAL_TC_PROFILING + std::cerr << "Tangential complex fixed in " << t.elapsed() + << " seconds." << std::endl; +#endif + } std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, @@ -1400,15 +1514,29 @@ next_face: == current_dim); // P: list of current_DT_face points (including 'i') - std::vector P( - current_DT_face.begin(), current_DT_face.end()); - P.push_back(center_vertex); + std::vector P; + P.reserve(current_DT_face.size() + 1); + for (DT_face::const_iterator it = current_DT_face.begin(), + it_end = current_DT_face.end() ; it != it_end ; ++it) + { + P.push_back((*it)->point()); + } + P.push_back(center_vertex->point()); + + // Q: vertices which are common neighbors of all vertices of P + std::vector Q; + P.reserve(curr_neighbors.size()); + for (Neighbor_vertices::const_iterator it = curr_neighbors.begin(), + it_end = curr_neighbors.end() ; it != it_end ; ++it) + { + Q.push_back((*it)->point()); + } bool does_intersect = does_voronoi_face_and_tangent_subspace_intersect( triangulation_dim, P, - curr_neighbors, + Q, tsb, local_tr_traits); if (does_intersect) @@ -1820,6 +1948,24 @@ next_face: w - m_k.squared_distance_d_object()(p, projected_pt) ); } + + // Project all the points in the tangent space + template + std::vector project_points_and_compute_weights( + const Indexed_point_range &point_indices, + const Tangent_space_basis &tsb, + const Tr_traits &tr_traits) const + { + std::vector ret; + for (typename Indexed_point_range::const_iterator + it = point_indices.begin(), it_end = point_indices.end(); + it != it_end ; ++it) + { + ret.push_back(project_point_and_compute_weight( + m_points[*it], m_weights[*it], tsb, tr_traits)); + } + return ret; + } // A simplex here is a local tri's full cell handle bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) const @@ -1890,10 +2036,9 @@ next_face: } // A simplex here is a list of point indices + // CJTODO: improve it like the other "is_simplex_consistent" below bool is_simplex_consistent(std::set const& simplex) const { - int cur_dim_plus_1 = static_cast(simplex.size()); - // Check if the simplex is in the stars of all its vertices std::set::const_iterator it_point_idx = simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p @@ -1908,16 +2053,75 @@ next_face: Star const& star = m_stars[point_idx]; // What we're looking for is "simplex" \ point_idx - Incident_simplex ic_to_find = simplex; - ic_to_find.erase(point_idx); + Incident_simplex is_to_find = simplex; + is_to_find.erase(point_idx); // For each cell - if (std::find(star.begin(), star.end(), ic_to_find) == star.end()) + if (std::find(star.begin(), star.end(), is_to_find) == star.end()) return false; } return true; } + + // A simplex here is a list of point indices + // "s" contains all the points of the simplex except "center_point" + // This function returns the points whose star doesn't contain the simplex + // N.B.: the function assumes that the simplex is contained in + // star(center_point) + template // value_type = std::size_t + bool is_simplex_consistent( + std::size_t center_point, + Incident_simplex const& s, // without "center_point" + OutputIterator points_whose_star_does_not_contain_s, + bool check_also_in_non_maximal_faces = false) const + { + std::set full_simplex = s; + full_simplex.insert(center_point); + + // Check if the simplex is in the stars of all its vertices + Incident_simplex::const_iterator it_point_idx = s.begin(); + // For each point p of the simplex, we parse the incidents cells of p + // and we check if "simplex" is among them + for ( ; it_point_idx != s.end() ; ++it_point_idx) + { + std::size_t point_idx = *it_point_idx; + // Don't check infinite simplices + if (point_idx == std::numeric_limits::max()) + continue; + + Star const& star = m_stars[point_idx]; + + // What we're looking for is full_simplex \ point_idx + Incident_simplex is_to_find = full_simplex; + is_to_find.erase(point_idx); + + if (check_also_in_non_maximal_faces) + { + // For each simplex "is" of the star, check if ic_to_simplex is + // included in "is" + bool found = false; + for (Star::const_iterator is = star.begin(), is_end = star.end() ; + !found && is != is_end ; ++is) + { + if (std::includes(is->begin(), is->end(), + is_to_find.begin(), is_to_find.end())) + found = true; + } + + if (!found) + *points_whose_star_does_not_contain_s++ = point_idx; + } + else + { + // Does the star contain is_to_find? + if (std::find(star.begin(), star.end(), is_to_find) == star.end()) + *points_whose_star_does_not_contain_s++ = point_idx; + } + } + + return true; + } #ifdef CGAL_LINKED_WITH_TBB // Functor for try_to_solve_inconsistencies_in_a_local_triangulation function @@ -2688,10 +2892,10 @@ next_face: Star const& star = m_stars[point_idx]; // What we're looking for is "simplex" \ point_idx - Incident_simplex ic_to_find = simplex; - ic_to_find.erase(point_idx); + Incident_simplex is_to_find = simplex; + is_to_find.erase(point_idx); - if (std::find(star.begin(), star.end(), ic_to_find) == star.end()) + if (std::find(star.begin(), star.end(), is_to_find) == star.end()) { solve_inconsistency_by_adding_higher_dimensional_simplices( tr_index, *it_point_idx, simplex); @@ -2724,15 +2928,17 @@ next_face: return inconsistencies_found; } - + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template + // Note the computation is made in local coordinates. "tsb"'s vectors are not + // used because these vectors become (0..., 1..., 0) in local coordinates. + template CGAL::Quadratic_program_solution compute_voronoi_face_and_tangent_subspace_LP_problem( int points_dim, - VH_range_a const& P, - VH_range_b const& Q, + Weighted_point_range_a const& P, + Weighted_point_range_b const& Q, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { @@ -2767,15 +2973,15 @@ next_face: //=========== First set of equations =========== // For points pi in P // 2(p0 - pi).x = p0^2 - wght(p0) - pi^2 + wght(pi) - typename VH_range_a::const_iterator it_vh = P.begin(); - Tr_point const& p0 = (*it_vh)->point(); + typename Weighted_point_range_a::const_iterator it_p = P.begin(); + Tr_point const& p0 = *it_p; FT const w0 = point_weight(p0); FT p0_dot_p0 = scalar_pdct(pt_to_vec(drop_w(p0)), pt_to_vec(drop_w(p0))); - ++it_vh; - for (typename VH_range_a::const_iterator it_vh_end = P.end() ; - it_vh != it_vh_end ; ++it_vh) + ++it_p; + for (typename Weighted_point_range_a::const_iterator it_p_end = P.end() ; + it_p != it_p_end ; ++it_p) { - Tr_point const& pi = (*it_vh)->point(); + Tr_point const& pi = *it_p; FT const wi = point_weight(pi); for (int k = 0 ; k < points_dim ; ++k) @@ -2791,11 +2997,11 @@ next_face: //=========== Second set of equations =========== // For each point qi in Q // 2(qi - p0).x <= qi^2 - wght(pi) - p0^2 + wght(p0) - for (typename VH_range_b::const_iterator it_vh = Q.begin(), - it_vh_end = Q.end() ; - it_vh != it_vh_end ; ++it_vh) + for (typename Weighted_point_range_b::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; + it_q != it_q_end ; ++it_q) { - Tr_point const& qi = (*it_vh)->point(); + Tr_point const& qi = *it_q; FT const wi = point_weight(qi); for (int k = 0 ; k < points_dim ; ++k) @@ -2810,7 +3016,7 @@ next_face: //=========== Third set of equations =========== // For each thickening vector bj of TSB, // x.bj <= alpha_plus and >= alpha_minus - // where bj is in the TSB => bj = (0..., 1..., 0) (1 is at the ith position) + // where bj is in the TSB => bj = (0..., 1..., 0) (1 is at the jth position) // x.bj <= alpha_plus // -x.bj <= -alpha_minus std::size_t j = points_dim - tsb.num_thickening_vectors(); @@ -2844,11 +3050,11 @@ next_face: // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template + template bool does_voronoi_face_and_tangent_subspace_intersect( int points_dim, - VH_range_a const& P, - VH_range_b const& Q, + Weighted_point_range_a const& P, + Weighted_point_range_b const& Q, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { @@ -2859,37 +3065,41 @@ next_face: // Returns any point of the intersection between aff(voronoi_cell) and a // tangent space. // P: dual face in Delaunay triangulation (p0, p1, ..., pn) - template - boost::optional + // Return value: the point coordinates are expressed in the tsb base + template + boost::optional compute_aff_of_voronoi_face_and_tangent_subspace_intersection( int points_dim, - VH_range_a const& P, + Weighted_point_range const& P, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { // As we're only interested by aff(v), Q is empty return compute_voronoi_face_and_tangent_subspace_intersection( - points_dim, P, std::vector(), tsb, tr_traits); + points_dim, P, std::vector(), + tsb, tr_traits); } // Returns any point of the intersection between a Voronoi cell and a // tangent space. // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template - boost::optional compute_voronoi_face_and_tangent_subspace_intersection( + // Return value: the point coordinates are expressed in the tsb base + template + boost::optional + compute_voronoi_face_and_tangent_subspace_intersection( int points_dim, - VH_range_a const& P, - VH_range_b const& Q, + Weighted_point_range_a const& P, + Weighted_point_range_b const& Q, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { typedef CGAL::Quadratic_program_solution LP_solution; LP_solution sol = compute_voronoi_face_and_tangent_subspace_LP_problem( - points_dim, center_vh, P, Q, tsb, tr_traits); + points_dim, P, Q, tsb, tr_traits); - boost::optional ret; + boost::optional ret; if (sol.status() == CGAL::QP_OPTIMAL) { std::vector p; @@ -2901,7 +3111,7 @@ next_face: { p.push_back(to_double(*it_v)); } - ret = m_k.construct_point_d_object()(points_dim, p.begin(), p.end()); + ret = tr_traits.construct_point_d_object()(points_dim, p.begin(), p.end()); } else { From 0a0714aa44492fd22d195946eeeed10f4b4e5e4f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 18:49:11 +0200 Subject: [PATCH 304/487] One priority queue per dimension --- Tangential_complex/include/CGAL/Tangential_complex.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6b2a27e3769..59ac7edce50 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -780,7 +780,10 @@ public: std::vector, std::greater > AATC_pq; - AATC_pq pqueue; + // One queue per dimension, from intrinsic dim (index = 0) to + // ambiant dim (index = ambiant - intrinsic dim) + std::vector pqueues; + pqueues.resize(m_ambient_dim - m_intrinsic_dimension + 1); // For each triangulation for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) @@ -796,6 +799,8 @@ public: if (*s.rbegin() == std::numeric_limits::max()) continue; + int simplex_dim = s.size(); + // P: points whose star does not contain "s" std::vector P; is_simplex_consistent(idx, s, std::back_inserter(P), true); @@ -826,8 +831,8 @@ public: Vector thickening_v = k_diff_points(inters_global, m_points[p]); FT squared_alpha = k_sqlen(thickening_v); - pqueue.push(Simplex_and_alpha( - p, full_simplex, squared_alpha, thickening_v)); + pqueues[simplex_dim - m_intrinsic_dimension].push( + Simplex_and_alpha(p, full_simplex, squared_alpha, thickening_v)); } } } From a3bd61fa73b2a8321985811b3bc7f6eab5fb9c53 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 18:50:43 +0200 Subject: [PATCH 305/487] m_intrinsic_dimension => m_intrinsic_dim --- .../include/CGAL/Tangential_complex.h | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 59ac7edce50..a33f9bff46f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -278,7 +278,7 @@ public: const Kernel &k = Kernel() ) : m_k(k), - m_intrinsic_dimension(intrinsic_dimension), + m_intrinsic_dim(intrinsic_dimension), m_half_sparsity(0.5*sparsity), m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), m_ambient_dim(k.point_dimension_d_object()(*first)), @@ -314,7 +314,7 @@ public: int intrinsic_dimension() const { - return m_intrinsic_dimension; + return m_intrinsic_dim; } int ambient_dimension() const { @@ -415,7 +415,7 @@ public: std::vector sum_eigen_values(m_ambient_dim, FT(0)); std::size_t num_points_for_pca = - std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dimension); + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim); typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -783,7 +783,7 @@ public: // One queue per dimension, from intrinsic dim (index = 0) to // ambiant dim (index = ambiant - intrinsic dim) std::vector pqueues; - pqueues.resize(m_ambient_dim - m_intrinsic_dimension + 1); + pqueues.resize(m_ambient_dim - m_intrinsic_dim + 1); // For each triangulation for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) @@ -831,7 +831,7 @@ public: Vector thickening_v = k_diff_points(inters_global, m_points[p]); FT squared_alpha = k_sqlen(thickening_v); - pqueues[simplex_dim - m_intrinsic_dimension].push( + pqueues[simplex_dim - m_intrinsic_dim].push( Simplex_and_alpha(p, full_simplex, squared_alpha, thickening_v)); } } @@ -883,7 +883,7 @@ public: << std::endl; } - if (m_intrinsic_dimension < 1 || m_intrinsic_dimension > 3) + if (m_intrinsic_dim < 1 || m_intrinsic_dim > 3) { std::cerr << "Error: export_to_off => intrinsic dimension should be " "between 1 and 3." @@ -1007,9 +1007,9 @@ public: cit != ambient_dt.finite_full_cells_end() ; ++cit ) { int lowest_dim = - (check_for_any_dimension_simplices ? 1 : m_intrinsic_dimension); + (check_for_any_dimension_simplices ? 1 : m_intrinsic_dim); int highest_dim = - (check_for_any_dimension_simplices ? m_ambient_dim : m_intrinsic_dimension); + (check_for_any_dimension_simplices ? m_ambient_dim : m_intrinsic_dim); for (int dim = lowest_dim ; dim <= highest_dim ; ++dim) { @@ -1609,7 +1609,7 @@ next_face: typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts; - ts.reserve(m_intrinsic_dimension); + ts.reserve(m_intrinsic_dim); ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); @@ -1621,13 +1621,13 @@ next_face: // CJTODO: this is only for torus_d Tangent_space_basis ts(p); - ts.reserve(m_intrinsic_dimension); - for (int dim = 0 ; dim < m_intrinsic_dimension ; ++dim) + ts.reserve(m_intrinsic_dim); + for (int dim = 0 ; dim < m_intrinsic_dim ; ++dim) { std::vector tt(m_ambient_dim, 0.); tt[2*dim] = -p[2*dim + 1]; tt[2*dim + 1] = p[2*dim]; - Vector t(2*m_intrinsic_dimension, tt.begin(), tt.end()); + Vector t(2*m_intrinsic_dim, tt.begin(), tt.end()); ts.push_back(t); } @@ -1640,7 +1640,7 @@ next_face: #else unsigned int num_points_for_pca = static_cast( - std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dimension)); + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); // Kernel functors typename Kernel::Construct_vector_d constr_vec = @@ -1699,7 +1699,7 @@ next_face: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues for (int j = m_ambient_dim - 1 ; - j >= m_ambient_dim - m_intrinsic_dimension ; + j >= m_ambient_dim - m_intrinsic_dim ; --j) { if (normalize_basis) @@ -1721,7 +1721,7 @@ next_face: if (p_orth_space_basis) { p_orth_space_basis->origin() = p; - for (int j = m_ambient_dim - m_intrinsic_dimension - 1 ; + for (int j = m_ambient_dim - m_intrinsic_dim - 1 ; j >= 0 ; --j) { @@ -1743,7 +1743,7 @@ next_face: } #if defined(CGAL_ALPHA_TC) && defined(CGAL_USE_A_FIXED_ALPHA) // Add the orthogonal vectors as "thickening vectors" - for (int j = m_ambient_dim - m_intrinsic_dimension - 1 ; + for (int j = m_ambient_dim - m_intrinsic_dim - 1 ; j >= 0 ; --j) { @@ -1774,7 +1774,7 @@ next_face: //Vector t1(12., 15., 65.); //Vector t2(32., 5., 85.); //Tangent_space_basis ts; - //ts.reserve(m_intrinsic_dimension); + //ts.reserve(m_intrinsic_dim); //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); //ts = compute_gram_schmidt_basis(ts, m_k); @@ -1838,7 +1838,7 @@ next_face: tr_traits.compute_coordinate_d_object(); Point global_point = tsb.origin(); - for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + for (int i = 0 ; i < m_intrinsic_dim ; ++i) global_point = k_transl(global_point, k_scaled_vec(tsb[i], coord(p, i))); @@ -1848,7 +1848,7 @@ next_face: { global_point = k_transl( global_point, - k_scaled_vec(tv[i].vec, coord(p, m_intrinsic_dimension + i))); + k_scaled_vec(tv[i].vec, coord(p, m_intrinsic_dim + i))); } #endif return global_point; @@ -1868,7 +1868,7 @@ next_face: std::vector coords; // Ambiant-space coords of the projected point coords.reserve(tsb.dimension()); - for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) + for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { // Local coords are given by the inner product with the vectors of tsb FT coord = inner_pdct(v, tsb[i]); @@ -1920,7 +1920,7 @@ next_face: // Ambiant-space coords of the projected point std::vector p_proj(ccci(tsb.origin()), ccci(tsb.origin(), 0)); coords.reserve(tsb.dimension()); - for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) + for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { // Local coords are given by the inner product with the vectors of tsb FT c = inner_pdct(v, tsb[i]); @@ -2206,7 +2206,7 @@ next_face: CGAL::Random_points_in_ball_d tr_point_in_ball_generator( - m_intrinsic_dimension, + m_intrinsic_dim, m_random_generator.get_double(0., m_half_sparsity)); Tr_point local_random_transl = @@ -2214,7 +2214,7 @@ next_face: *tr_point_in_ball_generator++, 0); Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; - for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + for (int i = 0 ; i < m_intrinsic_dim ; ++i) { global_transl = k_transl( global_transl, @@ -2386,7 +2386,7 @@ next_face: KNS_range kns_range = m_points_ds.query_ANN( global_center, - CGAL_TC_NUMBER_OF_PERTURBED_POINTS(m_intrinsic_dimension)); + CGAL_TC_NUMBER_OF_PERTURBED_POINTS(m_intrinsic_dim)); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; nn_it != kns_range.end() ; @@ -2451,10 +2451,10 @@ next_face: return os; } - // If m_intrinsic_dimension = 1, we output each point two times + // If m_intrinsic_dim = 1, we output each point two times // to be able to export each segment as a flat triangle with 3 different // indices (otherwise, Meshlab detects degenerated simplices) - const int N = (m_intrinsic_dimension == 1 ? 2 : 1); + const int N = (m_intrinsic_dim == 1 ? 2 : 1); // Kernel functors typename Kernel::Compute_coordinate_d coord = @@ -2723,7 +2723,7 @@ next_face: // CJTODO TEMP DEBUG // If co-intrinsic dimension = 1, let's compare normals - /*if (m_ambient_dim - m_intrinsic_dimension == 1) + /*if (m_ambient_dim - m_intrinsic_dim == 1) { typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); @@ -2748,7 +2748,7 @@ next_face: << inconsistent_simplex.size() - 1 << " simplex\n"; // If co-intrinsic dimension = 1, let's compare normals - /*if (m_ambient_dim - m_intrinsic_dimension == 1) + /*if (m_ambient_dim - m_intrinsic_dim == 1) { std::cerr << "(dot product between normals = "; std::set::const_iterator it_v = @@ -2908,7 +2908,7 @@ next_face: break; } // CJTODO TEMP - /*else if (m_ambient_dim - m_intrinsic_dimension == 1) + /*else if (m_ambient_dim - m_intrinsic_dim == 1) { typename Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); @@ -3269,7 +3269,7 @@ next_face: std::set > const *p_simpl_to_color_in_blue = NULL) const { - // If m_intrinsic_dimension = 1, each point is output two times + // If m_intrinsic_dim = 1, each point is output two times // (see export_vertices_to_off) num_OFF_simplices = 0; std::size_t num_maximal_simplices = 0; @@ -3285,7 +3285,7 @@ next_face: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - if (&tr == NULL || tr.current_dimension() < m_intrinsic_dimension) + if (&tr == NULL || tr.current_dimension() < m_intrinsic_dim) continue; // Color for this star @@ -3343,11 +3343,11 @@ next_face: } } - // If m_intrinsic_dimension = 1, each point is output two times, + // If m_intrinsic_dim = 1, each point is output two times, // so we need to multiply each index by 2 // And if only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) - if (m_intrinsic_dimension == 1) + if (m_intrinsic_dim == 1) { std::set tmp_c; std::set::iterator it = c.begin(); @@ -3408,7 +3408,7 @@ next_face: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != (m_intrinsic_dimension == 1 ? 2*idx : idx) + if (*c.begin() != (m_intrinsic_dim == 1 ? 2*idx : idx) && color_simplex == -1) continue; @@ -3474,7 +3474,7 @@ public: typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; - // If m_intrinsic_dimension = 1, each point is output two times + // If m_intrinsic_dim = 1, each point is output two times // (see export_vertices_to_off) num_OFF_simplices = 0; std::size_t num_maximal_simplices = 0; @@ -3521,14 +3521,14 @@ public: std::size_t num_vertices = c.size(); // Do not export smaller dimension simplices - if (num_vertices < m_intrinsic_dimension + 1) + if (num_vertices < m_intrinsic_dim + 1) continue; - // If m_intrinsic_dimension = 1, each point is output two times, + // If m_intrinsic_dim = 1, each point is output two times, // so we need to multiply each index by 2 // And if only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) - if (m_intrinsic_dimension == 1) + if (m_intrinsic_dim == 1) { std::set tmp_c; std::set::iterator it = c.begin(); @@ -3617,7 +3617,7 @@ public: { std::ofstream csv_consistent("output/correlation_consistent.csv"); // CJTODO TEMP std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO TEMP - if (m_intrinsic_dimension < 3) + if (m_intrinsic_dim < 3) { std::cerr << std::endl << "==========================================================" << std::endl @@ -3684,7 +3684,7 @@ public: private: const Kernel m_k; - const int m_intrinsic_dimension; + const int m_intrinsic_dim; const double m_half_sparsity; const double m_sq_half_sparsity; const int m_ambient_dim; From 95fc8dfdb8021c426606572c4596772ef8b10e36 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 19:38:57 +0200 Subject: [PATCH 306/487] Added/renamed typedefs --- .../include/CGAL/Tangential_complex.h | 151 +++++++++--------- 1 file changed, 79 insertions(+), 72 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index a33f9bff46f..c2e14adaa51 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -213,13 +213,28 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; +public: + typedef typename std::vector TS_container; + typedef typename std::vector OS_container; +private: + typedef typename std::vector Tr_container; + typedef typename std::vector Vectors; + + // An Incident_simplex is the list of the vertex indices + // except the center vertex + typedef std::set Incident_simplex; + typedef std::set Indexed_simplex; + typedef std::vector Star; + typedef std::vector Stars_container; + + // For the priority queues of solve_inconsistencies_using_adaptive_alpha_TC class Simplex_and_alpha { public: Simplex_and_alpha() {} Simplex_and_alpha( std::size_t center_point_index, - std::set const& simplex, // including "center_point_index" + Incident_simplex const& simplex, // NOT including "center_point_index" FT squared_alpha, Vector const& thickening_vector) : m_center_point_index(center_point_index), @@ -236,24 +251,11 @@ class Tangential_complex private: std::size_t m_center_point_index; // P - std::set m_simplex; // Missing simplex (includes P) + Incident_simplex m_simplex; // Missing simplex (does NOT includes P) FT m_squared_alpha; Vector m_thickening_vector; // (P, Cq) }; -public: - typedef typename std::vector TS_container; - typedef typename std::vector OS_container; -private: - typedef typename std::vector Tr_container; - typedef typename std::vector Vectors; - - // An Incident_simplex is the list of the vertex indices - // except the center vertex - typedef std::set Incident_simplex; - typedef std::vector Star; - typedef std::vector Stars_container; - // For transform_iterator static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) { @@ -658,7 +660,7 @@ public: if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; c.insert(idx); // Add the missing index if (!is_simplex_consistent(c)) @@ -707,7 +709,7 @@ public: == std::numeric_limits::max()) continue; - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); // Add the missing center vertex @@ -755,6 +757,7 @@ public: << std::endl; } + void solve_inconsistencies_using_adaptive_alpha_TC() { #ifdef CGAL_TC_PROFILING @@ -774,15 +777,16 @@ public: m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); //------------------------------------------------------------------------- - //1. Fill priority queue + // 1. Fill priority queues //------------------------------------------------------------------------- typedef std::priority_queue, std::greater > AATC_pq; + typedef std::vector PQueues; // One queue per dimension, from intrinsic dim (index = 0) to // ambiant dim (index = ambiant - intrinsic dim) - std::vector pqueues; + PQueues pqueues; pqueues.resize(m_ambient_dim - m_intrinsic_dim + 1); // For each triangulation @@ -799,7 +803,7 @@ public: if (*s.rbegin() == std::numeric_limits::max()) continue; - int simplex_dim = s.size(); + int simplex_dim = static_cast(s.size()); // P: points whose star does not contain "s" std::vector P; @@ -808,13 +812,13 @@ public: if (!P.empty()) { Triangulation const& q_tr = m_triangulations[idx].tr(); - std::set full_simplex = s; + Indexed_simplex full_simplex = s; full_simplex.insert(idx); for (std::vector::const_iterator it_p = P.begin(), it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { // star(p) does not contain "s" - std::size_t const& p = *it_p; + std::size_t p = *it_p; Tr_bare_point intersection = *compute_aff_of_voronoi_face_and_tangent_subspace_intersection( @@ -831,8 +835,11 @@ public: Vector thickening_v = k_diff_points(inters_global, m_points[p]); FT squared_alpha = k_sqlen(thickening_v); + // We insert full_simplex \ p + Incident_simplex is = full_simplex; + is.erase(p); pqueues[simplex_dim - m_intrinsic_dim].push( - Simplex_and_alpha(p, full_simplex, squared_alpha, thickening_v)); + Simplex_and_alpha(p, is, squared_alpha, thickening_v)); } } } @@ -848,9 +855,9 @@ public: std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, - std::set > const *p_simpl_to_color_in_red = NULL, - std::set > const *p_simpl_to_color_in_green = NULL, - std::set > const *p_simpl_to_color_in_blue = NULL) + std::set const *p_simpl_to_color_in_red = NULL, + std::set const *p_simpl_to_color_in_green = NULL, + std::set const *p_simpl_to_color_in_blue = NULL) const { return export_to_off( @@ -860,9 +867,9 @@ public: std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, - std::set > const *p_simpl_to_color_in_red = NULL, - std::set > const *p_simpl_to_color_in_green = NULL, - std::set > const *p_simpl_to_color_in_blue = NULL, + std::set const *p_simpl_to_color_in_red = NULL, + std::set const *p_simpl_to_color_in_green = NULL, + std::set const *p_simpl_to_color_in_blue = NULL, const Simplicial_complex *p_complex = NULL) const { if (m_points.empty()) @@ -945,7 +952,7 @@ public: if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; c.insert(idx); // Add the missing index sc.add_simplex(c); @@ -970,7 +977,7 @@ public: bool check_if_all_simplices_are_in_the_ambient_delaunay( const Simplicial_complex *p_complex = NULL, bool check_for_any_dimension_simplices = true, - std::set > * incorrect_simplices = NULL) const + std::set * incorrect_simplices = NULL) const { typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; @@ -1975,7 +1982,7 @@ next_face: // A simplex here is a local tri's full cell handle bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) const { - std::set c; + Indexed_simplex c; for (int i = 0 ; i < cur_dim + 1 ; ++i) { std::size_t data = fch->vertex(i)->data(); @@ -2042,10 +2049,10 @@ next_face: // A simplex here is a list of point indices // CJTODO: improve it like the other "is_simplex_consistent" below - bool is_simplex_consistent(std::set const& simplex) const + bool is_simplex_consistent(Indexed_simplex const& simplex) const { // Check if the simplex is in the stars of all its vertices - std::set::const_iterator it_point_idx = simplex.begin(); + Indexed_simplex::const_iterator it_point_idx = simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p // and we check if "simplex" is among them for ( ; it_point_idx != simplex.end() ; ++it_point_idx) @@ -2081,7 +2088,7 @@ next_face: OutputIterator points_whose_star_does_not_contain_s, bool check_also_in_non_maximal_faces = false) const { - std::set full_simplex = s; + Indexed_simplex full_simplex = s; full_simplex.insert(center_point); // Check if the simplex is in the stars of all its vertices @@ -2261,7 +2268,7 @@ next_face: if (*incident_simplex.rbegin() == std::numeric_limits::max()) continue; - std::set c = incident_simplex; + Indexed_simplex c = incident_simplex; c.insert(tr_index); // Add the missing index //***************************************************************************** @@ -2273,7 +2280,7 @@ next_face: { is_inconsistent = true; - for (std::set::const_iterator it = c.begin(); + for (Indexed_simplex::const_iterator it = c.begin(); it != c.end() ; ++it) { perturb(*it); @@ -2422,7 +2429,7 @@ next_face: perturb(tr_index); else { - std::set::const_iterator it_idx = c.begin(); + Indexed_simplex::const_iterator it_idx = c.begin(); std::advance(it_idx, rnd - 1); perturb(*it_idx); } @@ -2502,15 +2509,15 @@ next_face: void insert_higher_dim_simplex_into_star( std::size_t index, - const std::set &simplex) + const Indexed_simplex &simplex) { Incident_simplex incident_simplex = simplex; incident_simplex.erase(index); // Remove the center index Star &star = m_stars[index]; - std::set::const_iterator it_point_idx = simplex.begin(); - std::set::const_iterator it_point_idx_end = simplex.end(); + Indexed_simplex::const_iterator it_point_idx = simplex.begin(); + Indexed_simplex::const_iterator it_point_idx_end = simplex.end(); for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { // Skip center index @@ -2533,12 +2540,12 @@ next_face: // "inconsistent_simplex" must be in star(p) but not in star(q) void solve_inconsistency_by_adding_higher_dimensional_simplices( std::size_t p_idx, std::size_t q_idx, - const std::set &inconsistent_simplex) + const Indexed_simplex &inconsistent_simplex) { CGAL_assertion_code( - std::set inc_s_minus_p = inconsistent_simplex; + Indexed_simplex inc_s_minus_p = inconsistent_simplex; inc_s_minus_p.erase(p_idx); - std::set inc_s_minus_q = inconsistent_simplex; + Indexed_simplex inc_s_minus_q = inconsistent_simplex; inc_s_minus_q.erase(q_idx); ); CGAL_assertion(std::find(m_stars[p_idx].begin(), m_stars[p_idx].end(), @@ -2582,9 +2589,9 @@ next_face: // other threads are perturbing the positions const Point pt_p = compute_perturbed_point(p_idx); - std::set::const_iterator it_point_idx = + Indexed_simplex::const_iterator it_point_idx = inconsistent_simplex.begin(); - std::set::const_iterator it_point_idx_end = + Indexed_simplex::const_iterator it_point_idx_end = inconsistent_simplex.end(); // For each point of the simplex, we reproject it onto the tangent // space. Could be optimized since it's already been computed before. @@ -2751,7 +2758,7 @@ next_face: /*if (m_ambient_dim - m_intrinsic_dim == 1) { std::cerr << "(dot product between normals = "; - std::set::const_iterator it_v = + Indexed_simplex::const_iterator it_v = inconsistent_simplex.begin(); std::size_t i1 = *it_v; ++it_v; @@ -2855,7 +2862,7 @@ next_face: //------------------------------------------------------------------------- //7. Create a k+1-simplex (inconsistent_simplex, ti) //------------------------------------------------------------------------- - std::set new_simplex = inconsistent_simplex; + Indexed_simplex new_simplex = inconsistent_simplex; new_simplex.insert(inside_point_idx); it_point_idx = new_simplex.begin(); @@ -2874,7 +2881,7 @@ next_face: // Returns true if some inconsistencies were found. // Precondition: incident_simplex is in the star of m_points[tr_index] bool check_and_solve_inconsistencies_by_adding_higher_dim_simplices( - std::size_t tr_index, const std::set &incident_simplex) + std::size_t tr_index, const Incident_simplex &incident_simplex) { bool inconsistencies_found = false; @@ -2883,11 +2890,11 @@ next_face: == std::numeric_limits::max()) return false; - std::set simplex = incident_simplex; + Indexed_simplex simplex = incident_simplex; simplex.insert(tr_index); // Check if the simplex is in the stars of all its vertices - std::set::const_iterator it_point_idx = incident_simplex.begin(); + Incident_simplex::const_iterator it_point_idx = incident_simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p // and we check if "simplex" is among them for ( ; it_point_idx != incident_simplex.end() ; ++it_point_idx) @@ -3264,9 +3271,9 @@ next_face: std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_OFF_simplices, bool color_inconsistencies = false, - std::set > const *p_simpl_to_color_in_red = NULL, - std::set > const *p_simpl_to_color_in_green = NULL, - std::set > const *p_simpl_to_color_in_blue = NULL) + std::set const *p_simpl_to_color_in_red = NULL, + std::set const *p_simpl_to_color_in_green = NULL, + std::set const *p_simpl_to_color_in_blue = NULL) const { // If m_intrinsic_dim = 1, each point is output two times @@ -3294,8 +3301,8 @@ next_face: color << 128 << " " << 128 << " " << 128; // Gather the triangles here, with an int telling its color - typedef std::vector, int> > - Star_using_triangles; + typedef std::vector > + Star_using_triangles; Star_using_triangles star_using_triangles; // For each cell of the star @@ -3303,7 +3310,7 @@ next_face: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; c.insert(idx); std::size_t num_vertices = c.size(); ++num_maximal_simplices; @@ -3349,8 +3356,8 @@ next_face: // the file when m_intrinsic dim = 2) if (m_intrinsic_dim == 1) { - std::set tmp_c; - std::set::iterator it = c.begin(); + Indexed_simplex tmp_c; + Indexed_simplex::iterator it = c.begin(); for ( ; it != c.end() ; ++it) tmp_c.insert(*it * 2); if (num_vertices == 2) @@ -3370,8 +3377,8 @@ next_face: std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); do { - std::set triangle; - std::set::iterator it = c.begin(); + Indexed_simplex triangle; + Indexed_simplex::iterator it = c.begin(); for (int i = 0; it != c.end() ; ++i, ++it) { if (booleans[i]) @@ -3395,12 +3402,12 @@ next_face: == std::numeric_limits::max()) continue; - const std::set &c = it_simplex->first; + const Indexed_simplex &c = it_simplex->first; int color_simplex = it_simplex->second; std::stringstream sstr_c; - std::set::const_iterator it_point_idx = c.begin(); + Indexed_simplex::const_iterator it_point_idx = c.begin(); for ( ; it_point_idx != c.end() ; ++it_point_idx) { sstr_c << *it_point_idx << " "; @@ -3466,9 +3473,9 @@ public: std::ostream &export_simplices_to_off( const Simplicial_complex &complex, std::ostream & os, std::size_t &num_OFF_simplices, - std::set > const *p_simpl_to_color_in_red = NULL, - std::set > const *p_simpl_to_color_in_green = NULL, - std::set > const *p_simpl_to_color_in_blue = NULL) + std::set const *p_simpl_to_color_in_red = NULL, + std::set const *p_simpl_to_color_in_green = NULL, + std::set const *p_simpl_to_color_in_blue = NULL) const { typedef Simplicial_complex::Simplex Simplex; @@ -3530,8 +3537,8 @@ public: // the file when m_intrinsic dim = 2) if (m_intrinsic_dim == 1) { - std::set tmp_c; - std::set::iterator it = c.begin(); + Indexed_simplex tmp_c; + Indexed_simplex::iterator it = c.begin(); for ( ; it != c.end() ; ++it) tmp_c.insert(*it * 2); if (num_vertices == 2) @@ -3551,8 +3558,8 @@ public: std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); do { - std::set triangle; - std::set::iterator it = c.begin(); + Indexed_simplex triangle; + Indexed_simplex::iterator it = c.begin(); for (int i = 0; it != c.end() ; ++i, ++it) { if (booleans[i]) @@ -3573,7 +3580,7 @@ public: continue; os << 3 << " "; - std::set::const_iterator it_point_idx = it_tri->begin(); + Indexed_simplex::const_iterator it_point_idx = it_tri->begin(); for ( ; it_point_idx != it_tri->end() ; ++it_point_idx) { os << *it_point_idx << " "; @@ -3643,7 +3650,7 @@ public: if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; c.insert(idx); // Add the missing index double fatness = compute_simplex_fatness(c); From fa3b2d9bea15726247b3214ef25fa41f00b0fa08 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 25 Jun 2015 11:36:45 +0200 Subject: [PATCH 307/487] Bugfix in RTd: in dimension 2, the points were never hidden --- .../include/CGAL/Regular_triangulation.h | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 1e591d6101d..a70cc908131 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -112,7 +112,6 @@ public: using Base::rotate_rotor; using Base::infinite_vertex; using Base::insert_in_hole; - using Base::insert_outside_convex_hull_1; using Base::is_infinite; using Base::locate; using Base::points_begin; @@ -270,7 +269,9 @@ public: CGAL_assertion( Vertex_handle() != hint ); return insert(p, hint->full_cell()); } - + + Vertex_handle insert_outside_convex_hull_1( + const Weighted_point & p, Full_cell_handle s); Vertex_handle insert_outside_affine_hull(const Weighted_point &); Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, @@ -827,7 +828,7 @@ Regular_triangulation typename RTTraits::Point_weight_d pw = geom_traits().point_weight_d_object(); - if (pw(p) == pw(v->point())) + if (pw(p) = pw(v->point())) return v; // If dim == 0 and the new point has a bigger weight, // we replace the point @@ -843,22 +844,49 @@ Regular_triangulation // !NO break here! } default: - if( 1 == current_dimension() ) - { - if( Base::OUTSIDE_CONVEX_HULL == lt ) - { - return insert_outside_convex_hull_1(p, s); - } - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - return v; - } + if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) + return insert_outside_convex_hull_1(p, s); else return insert_in_conflicting_cell(p, s); break; } } +// NOT DOCUMENTED... +template < class RTTraits, class TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation +::insert_outside_convex_hull_1(const Weighted_point & p, Full_cell_handle s) +{ + // This is a special case for dimension 1, because in that case, the right + // infinite full_cell is not correctly oriented... (sice its first vertex is the + // infinite one... + + bool in_conflict = is_in_conflict(p, s); + + // If p is not in conflict with s, then p is hidden + // => we don't insert it + if (!in_conflict) + { + m_hidden_points.push_back(p); + return Vertex_handle(); + } + else + { + CGAL_precondition( is_infinite(s) ); + CGAL_precondition( 1 == current_dimension() ); + int inf_v_index = s->index(infinite_vertex()); + bool swap = (0 == s->neighbor(inf_v_index)->index(s)); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + if( swap ) + { + s->swap_vertices(0, 1); + } + return v; + } +} + template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation @@ -919,21 +947,15 @@ Regular_triangulation } default: { - if( 1 == current_dimension() ) + if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) { if (s->has_vertex(star_center)) - { - if( Base::OUTSIDE_CONVEX_HULL == lt ) - { return insert_outside_convex_hull_1(p, s); - } - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - return v; - } } else + { return insert_in_conflicting_cell(p, s, star_center); + } break; } } @@ -950,22 +972,7 @@ Regular_triangulation { typedef std::vector Full_cell_h_vector; - bool in_conflict; - if( current_dimension() < maximal_dimension() ) - { - Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), - power_test_in_flat_predicate()); - in_conflict = c(s); - } - else - { - Orientation_d ori = geom_traits().orientation_d_object(); - Power_test_d side = geom_traits().power_test_d_object(); - Conflict_pred_in_fullspace c(*this, p, ori, side); - in_conflict = c(s); - } + bool in_conflict = is_in_conflict(p, s); // If p is not in conflict with s, then p is hidden // => we don't insert it @@ -1069,7 +1076,7 @@ bool Regular_triangulation ::is_in_conflict(const Weighted_point & p, Full_cell_const_handle s) const { - CGAL_precondition( 2 <= current_dimension() ); + CGAL_precondition( 1 <= current_dimension() ); if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( @@ -1093,7 +1100,7 @@ typename Regular_triangulation::Facet Regular_triangulation ::compute_conflict_zone(const Weighted_point & p, const Full_cell_handle s, OutputIterator out) const { - CGAL_precondition( 2 <= current_dimension() ); + CGAL_precondition( 1 <= current_dimension() ); if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( From aa81039e071bb587593c5f6c7ad3f9c2a096b84e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 25 Jun 2015 20:35:50 +0200 Subject: [PATCH 308/487] Bugfix: == --- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index a70cc908131..02efd84268c 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -828,7 +828,7 @@ Regular_triangulation typename RTTraits::Point_weight_d pw = geom_traits().point_weight_d_object(); - if (pw(p) = pw(v->point())) + if (pw(p) == pw(v->point())) return v; // If dim == 0 and the new point has a bigger weight, // we replace the point From 99ce450f718ddcdd35d42361a438e2d789b9c5fd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 25 Jun 2015 20:37:22 +0200 Subject: [PATCH 309/487] First version of alpha TC Where the tangent spaces are progressively thickened to try to get rid of inconsistencies --- .../Tangential_complex/benchmark_script.txt | 73 ++- .../Tangential_complex/benchmark_tc.cpp | 17 +- .../include/CGAL/Tangential_complex.h | 504 +++++++++++++----- .../include/CGAL/Tangential_complex/config.h | 3 +- .../CGAL/Tangential_complex/utilities.h | 128 ++++- .../test/Tangential_complex/test_utilities.h | 100 +--- 6 files changed, 571 insertions(+), 254 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index fa30a289ffd..26ad4eaead0 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -2,29 +2,62 @@ # Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- +#---------------------------------------------------------------- Adaptive alpha TC tests ------------------------------------------------------------------------ +#generate_sphere_d 1 1 - 50 2 1 0.005 N Y N 3 1 #OK +#generate_torus_d N - - 15 2 1 0.05 N Y N 10 1 +#generate_sphere_d 0.302 3 - 50 3 2 0.005 N Y N 60 1 #OK +#generate_sphere_d 0.302 2 - 300 2 1 0.005 N Y N 60 1 +#generate_torus_3D 2 1 N 200 3 2 0.05 N Y N 600 1 #OK => tetraedra only +#data/fandisk.txt - - - 0 3 2 0.005 Y Y N 5 1 +generate_torus_d N 1 - 50 4 2 0.05 N Y N 3 1 #NOT OK: various errors +#generate_torus_d Y 1 - 2500 4 2 0.05 N Y N 3 1 #NOT OK +#generate_torus_d N - - 30 6 3 0.05 N Y N 300 1 +#generate_moment_curve 0 1 - 10 3 1 0.005 N Y N 60 1 +#generate_two_spheres_d 3 4 - 500 3 2 0.05 N Y N 10 1 #OK +#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N Y N 60 1 + #---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ -#generate_sphere_d 0.302 - - 70 2 1 0.005 N N Y 60 1 -#generate_sphere_d 0.5 - - 70 2 1 0.005 N N Y 60 1 -#generate_sphere_d 3 2 - 1000 3 2 0.05 N N Y 60 1 -#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N Y 60 1 -#generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N Y 60 1 -#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever -#generate_torus_3D 2 1 Y 150 3 2 0.05 Y N N 600 1 -#generate_torus_d N - - 30 2 1 0.01 Y N N 30 1 -#generate_torus_d Y - - 70 4 2 0.05 Y N N 30 1 -#generate_torus_d N - - 200 4 2 0.05 Y N N 30 1 -#generate_torus_d N - - 20000 4 2 0.65 Y N N 30 1 -#generate_torus_d N - - 10000 6 3 0.05 Y N N 300 1 -#generate_torus_d N - - 50000 6 3 0.05 Y N N 7000 1 -#generate_torus_d N - - 100000 6 3 0.05 Y N N 7000 1 -#generate_torus_d N - - 1000000 6 3 0.3 Y N N 3000 1 -#generate_torus_d Y - - 10000 8 4 0.05 Y N N 3600 1 +#generate_sphere_d 0.302 - - 70 2 1 0.005 N N N 60 1 +#generate_sphere_d 0.304 0 - 100 3 2 0.05 N N N 60 1 +#generate_sphere_d 3 0 - 100 4 3 0.05 N N N 60 1 +#generate_sphere_d 3 0 - 1000 5 4 0.05 N N N 60 1 +#generate_two_spheres_d 3 4 - 1000 3 2 0.05 N N N 10 1 +#generate_two_spheres_d 3 10 - 1000 4 3 0.05 N N N 10 1 +#generate_two_spheres_d 3 10 - 2000 5 4 0.05 N N N 10 1 +#generate_3sphere_and_circle_d 3 - - 100000 5 3 0.05 N N N 7000 1 +#generate_plane - - - 100 4 3 0.005 N N N 3000 1 +#generate_plane - - - 10 5 4 0.005 N N N 3000 1 +#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N N 60 1 +#generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N N 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N N N 60 1 #Takes forever +#generate_torus_3D 2 1 Y 150 3 2 0.05 N N N 600 1 +#generate_torus_3D 2 1 N 100000 3 2 0.55 N N N 600 1 +#generate_torus_d N - - 18 2 1 0.01 N N N 30 1 +#generate_torus_d N - - 50000 2 1 0.7 N N N 30 1 +#generate_torus_d Y - - 2 2 1 0 N N N 30 1 +#generate_torus_d Y - - 15 4 2 0.05 N N N 30 1 +#generate_torus_d N 0 - 150 4 2 0.05 N N N 10 1 +#generate_torus_d N - - 20000 4 2 1.0 N N N 30 1 +#generate_torus_d Y 0 - 5000 6 3 0.05 N N N 300 1 +#generate_torus_d N - - 20000 6 3 0.05 N N N 60 1 +#generate_torus_d N - - 100000 6 3 0.05 N N N 3000 1 +#generate_torus_d N - - 1000000 6 3 0.3 N N N 3000 1 +#generate_torus_d Y - - 1000 8 4 0.05 N N N 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.1 N N N 60 1 #---------------------------------------------------------- Spatial search benchmarking -------------------------------------------------------------- -generate_torus_d Y - - 1000000 30 15 0 Y N N 3600 1 -data/SO3_50000.txt - - - 0 9 3 0 Y Y N 60 1 -data/Cy8.txt - - - 0 24 2 0 N Y N 60 1 -data/buddha_100kv.txt - - - 0 3 2 0 N Y N 120 1 +#generate_torus_3D 2 1 Y 10000 3 2 0 Y N N 600 1 +#data/buddha_100kv.txt - - - 0 3 2 0 N Y N 120 1 +#generate_torus_d N - - 10000 30 15 0 Y N N 3600 1 +#generate_torus_d N - - 100000 12 6 0 Y N N 3600 1 +#data/SO3_50000.txt - - - 0 9 3 0 Y N N 60 1 +#data/Cy8.txt - - - 0 24 2 0 N Y N 60 1 +#generate_sphere_d 0.5 - - 10000 2 1 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 3 2 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 4 3 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 5 4 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 6 5 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 7 6 0 N N Y 60 1 #---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- #generate_sphere_d 4 - - 20 3 2 0.05 N Y N 60 1 diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 1545d2e20af..556208e190e 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -334,8 +334,9 @@ void make_tc(std::vector &points, } return;*/ // CJTODO TEMP =========================== - - //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); + + if (ambient_dim <= 4) + tc.check_if_all_simplices_are_in_the_ambient_delaunay(); //tc.check_correlation_between_inconsistencies_and_fatness(); @@ -405,8 +406,11 @@ void make_tc(std::vector &points, //========================================================================= t.reset(); // Try to solve the remaining inconstencies - //tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); +#ifdef CGAL_ALPHA_TC tc.solve_inconsistencies_using_adaptive_alpha_TC(); +#else + tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); +#endif fix2_time = t.elapsed(); t.reset(); max_dim = tc.export_TC(complex, false); /*std::set > not_delaunay_simplices; @@ -656,8 +660,8 @@ int main() { points = generate_points_on_sphere_d( num_points, ambient_dim, - std::atof(param1.c_str()), - std::atof(param2.c_str())); + std::atof(param1.c_str()), // radius + std::atof(param2.c_str())); // radius_noise_percentage } else if (input == "generate_two_spheres_d") { @@ -688,7 +692,8 @@ int main() points = generate_points_on_torus_d( num_points, intrinsic_dim, - param1 == "Y"); + param1 == "Y", // uniform + std::atof(param2.c_str())); // radius_noise_percentage } else if (input == "generate_klein_bottle_3D") { diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c2e14adaa51..8eb77e4866d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -70,6 +70,7 @@ //static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP //CJTODO: debug +//#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_2 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE @@ -228,9 +229,8 @@ private: typedef std::vector Stars_container; // For the priority queues of solve_inconsistencies_using_adaptive_alpha_TC - class Simplex_and_alpha + struct Simplex_and_alpha { - public: Simplex_and_alpha() {} Simplex_and_alpha( std::size_t center_point_index, @@ -249,7 +249,6 @@ private: return m_squared_alpha > other.m_squared_alpha; } - private: std::size_t m_center_point_index; // P Incident_simplex m_simplex; // Missing simplex (does NOT includes P) FT m_squared_alpha; @@ -758,6 +757,101 @@ public: } +#ifdef CGAL_ALPHA_TC +private: + + // Look in the star of point "i" for inconsistent simplices, compute + // an approximation of alpha for each one and push it into the priority + // queues. + // Returns the number of inconsistent simplices found + template + std::size_t fill_pqueues_for_alpha_tc(std::size_t i, PQueues &pqueues) + { + // Kernel/traits functors + typename Kernel::Difference_of_points_d k_diff_points = + m_k.difference_of_points_d_object(); + typename Kernel::Squared_length_d k_sqlen = + m_k.squared_length_d_object(); + typename Tr_traits::Construct_weighted_point_d constr_wp = + m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); + + std::size_t num_inconsistent_simplices = 0; + + // For each cell + Star::const_iterator it_inc_simplex = m_stars[i].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[i].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + Incident_simplex const& s = *it_inc_simplex; + + // Don't check infinite cells + if (*s.rbegin() == std::numeric_limits::max()) + continue; + + int simplex_dim = static_cast(s.size()); + + // P: points whose star does not contain "s" + std::vector P; + is_simplex_consistent(i, s, std::back_inserter(P), true); + + if (!P.empty()) + { + ++num_inconsistent_simplices; + + Triangulation const& q_tr = m_triangulations[i].tr(); + Indexed_simplex full_simplex = s; + full_simplex.insert(i); + for (std::vector::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) + { + // star(p) does not contain "s" + std::size_t p = *it_p; + + // Compute the intersection between aff(Voronoi_cell(s)) and Tq + boost::optional intersection = + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + q_tr.current_dimension(), + project_points_and_compute_weights( + full_simplex, m_tangent_spaces[i], q_tr.geom_traits()), + m_tangent_spaces[i], + q_tr.geom_traits()); + + // CJTODO: replace with an assertion? + if (!intersection) + { + std::cerr << "ERROR fill_pqueues_for_alpha_tc: " + "aff(Voronoi_cell(s)) and Tq do not intersect.\n"; + continue; + } + + // The following computations are done in the Euclidian space + Point inters_global = unproject_point( + constr_wp(*intersection, 0), m_tangent_spaces[i], + q_tr.geom_traits()); + Vector thickening_v = k_diff_points( + inters_global, compute_perturbed_point(p)); + FT squared_alpha = k_sqlen(thickening_v); + + // We insert full_simplex \ p + Incident_simplex is = full_simplex; + is.erase(p); + pqueues[simplex_dim - m_intrinsic_dim].push( + Simplex_and_alpha(p, is, squared_alpha, thickening_v)); + + // CJTODO TEMP + /*std::cerr + << "Just inserted the simplex "; + std::copy(full_simplex.begin(), full_simplex.end(), + std::ostream_iterator(std::cerr, ", ")); + std::cerr << "into pqueue (i = " << i << ")\n";*/ + } + } + } + + return num_inconsistent_simplices; + } + +public: void solve_inconsistencies_using_adaptive_alpha_TC() { #ifdef CGAL_TC_PROFILING @@ -767,14 +861,6 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Fixing inconsistencies using adaptive alpha TC..." << std::endl; #endif - - // Kernel/traits functors - typename Kernel::Difference_of_points_d k_diff_points = - m_k.difference_of_points_d_object(); - typename Kernel::Squared_length_d k_sqlen = - m_k.squared_length_d_object(); - typename Tr_traits::Construct_weighted_point_d constr_wp = - m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); //------------------------------------------------------------------------- // 1. Fill priority queues @@ -789,69 +875,133 @@ public: PQueues pqueues; pqueues.resize(m_ambient_dim - m_intrinsic_dim + 1); + std::size_t num_inconsistent_simplices = 0; // For each triangulation - for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + num_inconsistent_simplices += fill_pqueues_for_alpha_tc(i, pqueues); + +#ifdef CGAL_TC_VERBOSE + std::cerr + << "Num inconsistent simplices found when filling the priority queues: " + << num_inconsistent_simplices << std::endl; +#endif + + //------------------------------------------------------------------------- + // 2. Thicken tangent spaces to solve inconsistencies + //------------------------------------------------------------------------- + + // While there's elements to treat in the queues + for(;;) { - // For each cell - Star::const_iterator it_inc_simplex = m_stars[idx].begin(); - Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); - for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + // Pick the simplex with the lowest dimension and the lowest alpha + Simplex_and_alpha saa; + bool found_saa = false; + for (PQueues::iterator it_pq = pqueues.begin(), it_pq_end = pqueues.end(); + !found_saa && it_pq != it_pq_end ; ++it_pq) { - Incident_simplex const& s = *it_inc_simplex; - - // Don't check infinite cells - if (*s.rbegin() == std::numeric_limits::max()) - continue; - - int simplex_dim = static_cast(s.size()); - - // P: points whose star does not contain "s" - std::vector P; - is_simplex_consistent(idx, s, std::back_inserter(P), true); - - if (!P.empty()) + while (!found_saa && !it_pq->empty()) { - Triangulation const& q_tr = m_triangulations[idx].tr(); - Indexed_simplex full_simplex = s; - full_simplex.insert(idx); - for (std::vector::const_iterator it_p = P.begin(), - it_p_end = P.end() ; it_p != it_p_end ; ++it_p) - { - // star(p) does not contain "s" - std::size_t p = *it_p; + saa = it_pq->top(); + it_pq->pop(); - Tr_bare_point intersection = - *compute_aff_of_voronoi_face_and_tangent_subspace_intersection( - q_tr.current_dimension(), - project_points_and_compute_weights( - full_simplex, m_tangent_spaces[idx], q_tr.geom_traits()), - m_tangent_spaces[idx], - q_tr.geom_traits()); - - // The following computations are done in the Euclidian space - Point inters_global = unproject_point( - constr_wp(intersection, 0), m_tangent_spaces[idx], - q_tr.geom_traits()); - Vector thickening_v = k_diff_points(inters_global, m_points[p]); - FT squared_alpha = k_sqlen(thickening_v); - - // We insert full_simplex \ p - Incident_simplex is = full_simplex; - is.erase(p); - pqueues[simplex_dim - m_intrinsic_dim].push( - Simplex_and_alpha(p, is, squared_alpha, thickening_v)); - } + // Check if the simplex is still missing in the star + if (!is_simplex_in_star(saa.m_center_point_index, saa.m_simplex)) + found_saa = true; } } + + // If all the queues are empty, we're done! + if (!found_saa) + break; + + Tangent_space_basis &tangent_basis = + m_tangent_spaces[saa.m_center_point_index]; + + // If we're already in the ambiant dim, we just need to thicken the + // tangent subspace a bit more (see below) + if (tangent_basis.dimension() < m_ambient_dim) + { + // Otherwise, let's thicken the tangent space + bool vec_added = add_vector_to_orthonormal_basis( + tangent_basis, + saa.m_thickening_vector, + m_k, + FT(0), /* sqlen_threshold: default value */ + true /* add_to_thickening_vectors */); + + // CJTODO TEMP + if (!vec_added) + { + std::cerr << "FYI: the thickening vector was not added " + "to the basis since it was linearly dependent to it.\n"; + } + } + + // Update the alpha+/- values + tangent_basis.update_alpha_values_of_thickening_vectors( + saa.m_thickening_vector, m_k); + + // Recompute triangulation & star + compute_tangent_triangulation(saa.m_center_point_index); + +#ifdef CGAL_TC_PERFORM_EXTRA_CHECKS + if (!is_simplex_in_star(saa.m_center_point_index, saa.m_simplex)) + { + std::cerr + << "FAILED in solve_inconsistencies_using_adaptive_alpha_TC(): " + << "the simplex " << saa.m_center_point_index << ", "; + std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), + std::ostream_iterator(std::cerr, ", ")); + std::cerr << "was not added in the star\n"; + + Indexed_simplex full_s = saa.m_simplex; + full_s.insert(saa.m_center_point_index); + + // CJTODO TEMP + bool is_this_simplex_somewhere = false; + for(auto ii : saa.m_simplex) + { + Indexed_simplex z = full_s; + z.erase(ii); + if (is_simplex_in_star(ii, z)) + { + is_this_simplex_somewhere = true; + std::cerr << "The simplex is in star #" << ii << std::endl; + break; + } + } + if (!is_this_simplex_somewhere) + std::cerr << "WOW The simplex is NOWHERE!\n"; + + // CJTODO TEMP + if (is_simplex_in_the_ambient_delaunay(full_s)) + std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + else + std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + + } + // CJTODO TEMP + else + { + std::cerr << "SUCCESS in solve_inconsistencies_using_adaptive_alpha_TC(): " + << "the simplex " << saa.m_center_point_index << ", "; + std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), + std::ostream_iterator(std::cerr, ", ")); + std::cerr << "was successfully added in the star\n"; + } +#endif + + // It's not a problem if entries are duplicated in the pqueues + // since there's a check when we pop elements + fill_pqueues_for_alpha_tc(saa.m_center_point_index, pqueues); } - // CJTODO: the rest - #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex fixed in " << t.elapsed() << " seconds." << std::endl; #endif } +#endif // CGAL_ALPHA_TC std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, @@ -973,6 +1123,47 @@ public: } } + // Expensive! + bool is_simplex_in_the_ambient_delaunay( + Indexed_simplex const& s) const + { + //------------------------------------------------------------------------- + // Build the ambient Delaunay triangulation + // Then save its simplices into "amb_dt_simplices" + //------------------------------------------------------------------------- + + typedef Regular_triangulation_euclidean_traits RT_Traits; + typedef Regular_triangulation< + RT_Traits, + Triangulation_data_structure< + typename RT_Traits::Dimension, + Triangulation_vertex + > > RT; + typedef typename RT::Vertex_handle RT_VH; + typedef typename RT::Finite_full_cell_const_iterator FFC_it; + + RT ambient_dt(m_ambient_dim); + for (std::size_t i=0; idata() = i; + } + + for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; + cit != ambient_dt.finite_full_cells_end() ; ++cit ) + { + Indexed_simplex simplex; + for (int i = 0 ; i < m_ambient_dim + 1 ; ++i) + simplex.insert(cit->vertex(i)->data()); + + if (std::includes(simplex.begin(), simplex.end(), + s.begin(), s.end())) + return true; + } + + return false; + } bool check_if_all_simplices_are_in_the_ambient_delaunay( const Simplicial_complex *p_complex = NULL, @@ -1040,10 +1231,10 @@ public: Simplex_range const *p_simplices; + std::size_t num_infinite_cells = 0; + Simplex_range stars_simplices; if (!p_complex) { - Simplex_range stars_simplices; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation @@ -1064,7 +1255,7 @@ public: { if (tr.is_infinite(*it_c)) { - std::cerr << "Warning: infinite cell in star" << std::endl; + ++num_infinite_cells; continue; } Simplex simplex; @@ -1094,34 +1285,21 @@ public: std::inserter(*incorrect_simplices, incorrect_simplices->begin()) ); - if (!incorrect_simplices->empty()) - { - std::cerr - << "ERROR check_if_all_simplices_are_in_the_ambient_delaunay:" - << std::endl - << " Number of simplices in ambient RT: " << amb_dt_simplices.size() - << std::endl - << " Number of unique simplices in TC stars: " << p_simplices->size() - << std::endl - << " Number of wrong simplices: " << incorrect_simplices->size() - << std::endl; - return false; - } - else - { #ifdef CGAL_TC_VERBOSE - std::cerr - << "SUCCESS check_if_all_simplices_are_in_the_ambient_delaunay:" - << std::endl - << " Number of simplices in ambient RT: " << amb_dt_simplices.size() - << std::endl - << " Number of unique simplices in TC stars: " << p_simplices->size() - << std::endl - << " Number of wrong simplices: " << incorrect_simplices->size() - << std::endl; + std::cerr + << (incorrect_simplices->empty() ? "OK " : "ERROR ") + << "check_if_all_simplices_are_in_the_ambient_delaunay:" + << std::endl + << " Number of simplices in ambient RT: " << amb_dt_simplices.size() + << std::endl + << " Number of unique simplices in TC stars: " << p_simplices->size() + << std::endl + << " Number of infinite full cells in TC stars: " << num_infinite_cells + << std::endl + << " Number of wrong simplices: " << incorrect_simplices->size() + << std::endl; #endif - return true; - } + return incorrect_simplices->empty(); } private: @@ -1209,16 +1387,15 @@ private: } #endif - int triangulation_dim = local_triangulation_dim(i); + int tangent_space_dim = tangent_basis_dim(i); Triangulation &local_tr = - m_triangulations[i].construct_triangulation(triangulation_dim); + m_triangulations[i].construct_triangulation(tangent_space_dim); const Tr_traits &local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); - typename Kernel::Equal_d k_eq = m_k.equal_d_object(); // Triangulation's traits functor & objects typename Tr_traits::Point_weight_d point_weight = @@ -1234,10 +1411,10 @@ private: // Insert p Tr_point proj_wp; - if(k_eq(compute_perturbed_point(i), tsb.origin())) + if(i == tsb.origin()) { proj_wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(triangulation_dim, ORIGIN), + local_tr_traits.construct_point_d_object()(tangent_space_dim, ORIGIN), m_weights[i]); } else @@ -1278,7 +1455,6 @@ private: compute_perturbed_weighted_point( neighbor_point_idx, neighbor_pt, neighbor_weight); - // "4*m_sq_half_sparsity" because both points can be perturbed if (squared_star_sphere_radius_plus_margin && k_sqdist(center_pt, neighbor_pt) > *squared_star_sphere_radius_plus_margin) @@ -1298,7 +1474,7 @@ private: vh->data() = neighbor_point_idx; // Let's recompute squared_star_sphere_radius_plus_margin - if (local_tr.current_dimension() >= triangulation_dim) + if (local_tr.current_dimension() >= tangent_space_dim) { squared_star_sphere_radius_plus_margin = boost::none; // Get the incident cells and look for the biggest circumsphere @@ -1341,9 +1517,11 @@ private: if (squared_star_sphere_radius_plus_margin) { #ifdef CGAL_TC_PERTURB_WEIGHT + // "4*m_sq_half_sparsity" because both points can be perturbed squared_star_sphere_radius_plus_margin = *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; #else + // "2*m_half_sparsity" because both points can be perturbed squared_star_sphere_radius_plus_margin = CGAL::square( CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2*m_half_sparsity); @@ -1415,12 +1593,19 @@ private: // Update the associated star (in m_stars) //*************************************************** - int triangulation_dim = local_triangulation_dim(i); Triangulation &local_tr = m_triangulations[i].tr(); + int triangulation_dim = local_tr.current_dimension(); Tr_traits const& local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle center_vertex = m_triangulations[i].center_vertex(); Tangent_space_basis const& tsb = m_tangent_spaces[i]; +#ifdef CGAL_TC_PERFORM_EXTRA_CHECKS + if (triangulation_dim != tangent_basis_dim(i)) + std::cerr << "WARNING in update_star__with_thickening_vector: the " + "dimension of the local triangulation is different from " + "the dimension of the tangent space.\n"; +#endif + Star &star = m_stars[i]; star.clear(); int cur_dim_plus_1 = triangulation_dim + 1; @@ -1601,9 +1786,24 @@ next_face: #endif ) { -#ifdef CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 +#ifdef CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_2 + + double tt[2] = {p[1], -p[0]}; + Vector t(2, &tt[0], &tt[2]); + + // Normalize t1 and t2 + typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + + Tangent_space_basis ts(i); + ts.reserve(m_intrinsic_dim); + ts.push_back(scaled_vec(t, FT(1)/CGAL::sqrt(sqlen(t)))); + m_are_tangent_spaces_computed[i] = true; + + return ts; + +#elif defined(CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3) - // CJTODO: this is only for a sphere in R^3 double tt1[3] = {-p[1] - p[2], p[0], p[0]}; double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], p[2] * tt1[0] - p[0] * tt1[2], @@ -1615,7 +1815,7 @@ next_face: typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - Tangent_space_basis ts; + Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); @@ -1626,8 +1826,7 @@ next_face: #elif defined(CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D) - // CJTODO: this is only for torus_d - Tangent_space_basis ts(p); + Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); for (int dim = 0 ; dim < m_intrinsic_dim ; ++dim) { @@ -1701,7 +1900,7 @@ next_face: Eigen::MatrixXd cov = centered.adjoint() * centered; Eigen::SelfAdjointEigenSolver eig(cov); - Tangent_space_basis tsb(p); // p = compute_perturbed_point(i) here + Tangent_space_basis tsb(i); // p = compute_perturbed_point(i) here // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues @@ -1727,7 +1926,7 @@ next_face: if (p_orth_space_basis) { - p_orth_space_basis->origin() = p; + p_orth_space_basis->set_origin(i); for (int j = m_ambient_dim - m_intrinsic_dim - 1 ; j >= 0 ; --j) @@ -1791,7 +1990,7 @@ next_face: // Returns the dimension of the ith local triangulation // This is particularly useful for the alpha-TC - int local_triangulation_dim(std::size_t i) const + int tangent_basis_dim(std::size_t i) const { return m_tangent_spaces[i].dimension(); } @@ -1844,7 +2043,7 @@ next_face: typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object(); - Point global_point = tsb.origin(); + Point global_point = compute_perturbed_point(tsb.origin()); for (int i = 0 ; i < m_intrinsic_dim ; ++i) global_point = k_transl(global_point, k_scaled_vec(tsb[i], coord(p, i))); @@ -1870,7 +2069,7 @@ next_face: typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); - Vector v = diff_points(p, tsb.origin()); + Vector v = diff_points(p, compute_perturbed_point(tsb.origin())); std::vector coords; // Ambiant-space coords of the projected point @@ -1890,7 +2089,8 @@ next_face: coords.push_back(coord); } #endif - return Tr_bare_point(tsb.dimension(), coords.begin(), coords.end()); + return Tr_bare_point(static_cast( + coords.size()), coords.begin(), coords.end()); } // Project the point in the tangent space @@ -1921,11 +2121,15 @@ next_face: typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); - Vector v = diff_points(p, tsb.origin()); + Point origin = compute_perturbed_point(tsb.origin()); + Vector v = diff_points(p, origin); + + // Same dimension? Then the weight is 0 + bool same_dim = (point_dim == tsb.dimension()); std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(ccci(tsb.origin()), ccci(tsb.origin(), 0)); + std::vector p_proj(ccci(origin), ccci(origin, 0)); coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { @@ -1933,9 +2137,10 @@ next_face: FT c = inner_pdct(v, tsb[i]); coords.push_back(c); - // p_proj += c * v; - for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += c * coord(tsb[i], j); + // p_proj += c * tsb[i] + if (!same_dim) + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += c * coord(tsb[i], j); } #ifdef CGAL_ALPHA_TC @@ -1945,19 +2150,26 @@ next_face: FT c = inner_pdct(v, tv[i].vec); coords.push_back(c); - // p_proj += c * v; - for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += c * coord(tv[i].vec, j); + // p_proj += c * tv[i].vec + if (!same_dim) + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += c * coord(tv[i].vec, j); } #endif - Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); - + // Same dimension? Then the weight is 0 + FT sq_dist_to_proj_pt = 0; + if (!same_dim) + { + Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); + sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt); + } + return tr_traits.construct_weighted_point_d_object() ( tr_traits.construct_point_d_object()( - tsb.dimension(), coords.begin(), coords.end()), - w - m_k.squared_distance_d_object()(p, projected_pt) + static_cast(coords.size()), coords.begin(), coords.end()), + w - sq_dist_to_proj_pt ); } @@ -1974,7 +2186,7 @@ next_face: it != it_end ; ++it) { ret.push_back(project_point_and_compute_weight( - m_points[*it], m_weights[*it], tsb, tr_traits)); + compute_perturbed_weighted_point(*it), tsb, tr_traits)); } return ret; } @@ -2010,11 +2222,11 @@ next_face: std::size_t simplex_dim = s.size() - 1; // Compute basis - Tangent_space_basis basis(m_points[s[0]]); + Tangent_space_basis basis(s[0]); for (int j = 0 ; j < simplex_dim ; ++j) { Vector e = diff_pts( - m_points[s[j+1]], m_points[s[0]]); + compute_perturbed_point(s[j+1]), compute_perturbed_point(s[0])); basis.push_back(e); } basis = compute_gram_schmidt_basis(basis, m_k); @@ -2024,8 +2236,8 @@ next_face: for (int j = 0 ; j < simplex_dim ; ++j) { Tr_vector v_j = tr_diff_pts( - project_point(m_points[s[j+1]], basis), - project_point(m_points[s[0]], basis)); + project_point(compute_perturbed_point(s[j+1]), basis), + project_point(compute_perturbed_point(s[0]), basis)); for (int i = 0 ; i < simplex_dim ; ++i) m(j, i) = CGAL::to_double(coord(v_j, i)); } @@ -2039,7 +2251,8 @@ next_face: for ( ; !combi.finished() ; ++combi) { FT sq_length = sqdist( - m_points[s[combi[0]]], m_points[s[combi[1]]]); + compute_perturbed_point(s[combi[0]]), + compute_perturbed_point(s[combi[1]])); if (sq_length > max_sq_length) max_sq_length = sq_length; } @@ -2135,6 +2348,36 @@ next_face: return true; } + // A simplex here is a list of point indices + // It looks for s in star(p). + // "s" contains all the points of the simplex except p. + bool is_simplex_in_star( + std::size_t p, + Incident_simplex const& s, + bool check_also_in_non_maximal_faces = true) const + { + Star const& star = m_stars[p]; + + if (check_also_in_non_maximal_faces) + { + // For each simplex "is" of the star, check if ic_to_simplex is + // included in "is" + bool found = false; + for (Star::const_iterator is = star.begin(), is_end = star.end() ; + !found && is != is_end ; ++is) + { + if (std::includes(is->begin(), is->end(), s.begin(), s.end())) + found = true; + } + + return found; + } + else + { + return !(std::find(star.begin(), star.end(), s) == star.end()); + } + } + #ifdef CGAL_LINKED_WITH_TBB // Functor for try_to_solve_inconsistencies_in_a_local_triangulation function class Try_to_solve_inconsistencies_in_a_local_triangulation @@ -3250,8 +3493,8 @@ next_face: lp.set_a(k, current_row + 1, -coord(bi, k)); } - Point const& basis_origin = orthogonal_subspace_basis.origin(); - FT bi_dot_p = scalar_pdct(bi, pt_to_vec(basis_origin)); + FT bi_dot_p = scalar_pdct(bi, + pt_to_vec(compute_perturbed_point(orthogonal_subspace_basis.origin()))); lp.set_b(current_row , bi_dot_p + alpha); lp.set_b(current_row + 1, -bi_dot_p + alpha); @@ -3415,9 +3658,10 @@ next_face: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != (m_intrinsic_dim == 1 ? 2*idx : idx) + // CJTODO: uncomment? but it only works if there's no inconsistencies + /*if (*c.begin() != (m_intrinsic_dim == 1 ? 2*idx : idx) && color_simplex == -1) - continue; + continue;*/ os << 3 << " " << sstr_c.str(); if (color_inconsistencies || p_simpl_to_color_in_red diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 5ada1b8bbfa..9c26f718d30 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -33,12 +33,13 @@ //=========================== Alpha-TC or not? ================================ #define CGAL_ALPHA_TC - #define CGAL_USE_A_FIXED_ALPHA + //#define CGAL_USE_A_FIXED_ALPHA const double CGAL_TC_ALPHA_VALUE = 0.3; //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE +#define CGAL_TC_PERFORM_EXTRA_CHECKS //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES //#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index f0a8e7b99c4..c58b628fe5d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -145,24 +145,36 @@ namespace Tangential_complex_ { typedef typename Kernel::Vector_d Vector; typedef typename std::vector::const_iterator const_iterator; - Point m_origin; //fixme should probably be (const?) ref ? + std::size_t m_origin; std::vector m_vectors; - Point& origin() { return m_origin; } - const Point& origin() const { return m_origin; } + std::size_t origin() const { return m_origin; } + void set_origin(std::size_t o) { m_origin = o; } const_iterator begin() const { return m_vectors.begin(); } const_iterator end() const { return m_vectors.end(); } std::size_t size() const { return m_vectors.size(); } - Vector& operator[](const std::size_t i) { return m_vectors[i]; } - const Vector& operator[](const std::size_t i) const { return m_vectors[i]; } - void push_back(const Vector& v) { m_vectors.push_back(v); } - void reserve(const std::size_t s) { m_vectors.reserve(s); } + Vector& operator[](const std::size_t i) + { + return m_vectors[i]; + } + const Vector& operator[](const std::size_t i) const + { + return m_vectors[i]; + } + void push_back(const Vector& v) + { + m_vectors.push_back(v); + } + void reserve(const std::size_t s) + { + m_vectors.reserve(s); + } Basis() { } - Basis(const Point& p) : m_origin(p) { } - Basis(const Point& p, const std::vector& vectors) - : m_origin(p), m_vectors(vectors) + Basis(std::size_t origin) : m_origin(origin) { } + Basis(std::size_t origin, const std::vector& vectors) + : m_origin(origin), m_vectors(vectors) { } #ifdef CGAL_ALPHA_TC @@ -192,12 +204,32 @@ namespace Tangential_complex_ { { return m_thickening_vectors; } - void add_thickening_vector(Vector const& vec, FT alpha_minus, FT alpha_plus) + void add_thickening_vector( + Vector const& vec, FT alpha_minus = FT(0), FT alpha_plus = FT(0)) { m_thickening_vectors.push_back( Thickening_vector(vec, alpha_minus, alpha_plus)); } + void update_alpha_values_of_thickening_vectors( + Vector const& vec, Kernel const& k) + { + typename Kernel::Scalar_product_d k_scalar_pdct = + k.scalar_product_d_object(); + + for (Thickening_vectors::iterator it_v = m_thickening_vectors.begin(), + it_v_end = m_thickening_vectors.end() ; + it_v != it_v_end ; ++it_v) + { + const FT MARGIN = 0.001; // CJTODO TEMP + FT alpha_i = k_scalar_pdct(it_v->vec, vec); + if (alpha_i + MARGIN > it_v->alpha_plus) + it_v->alpha_plus = alpha_i + MARGIN; + else if (alpha_i - MARGIN < it_v->alpha_minus) + it_v->alpha_minus = alpha_i - MARGIN; + } + } + int dimension() const { return static_cast(m_vectors.size() + m_thickening_vectors.size()); @@ -209,11 +241,23 @@ namespace Tangential_complex_ { } #endif }; - + + // Using Gram-Schmidt + // * If the resulting vector after G-S algorithm is below "sqlen_threshold", + // the vector considered linearly dependend to the existing vectors + // and is not added to the basis + // * Returns true if the vector was added to the basis template - Basis compute_gram_schmidt_basis(Basis const& input_basis, K const& k) + bool add_vector_to_orthonormal_basis( + Basis & basis, typename K::Vector_d const& v, K const& k, + typename K::FT sqlen_threshold = typename K::FT(1e-13) +#ifdef CGAL_ALPHA_TC + , bool add_to_thickening_vectors = false +#endif + ) { typedef Basis Basis; + typedef typename K::FT FT; typedef typename K::Vector_d Vector; // Kernel functors @@ -221,23 +265,57 @@ namespace Tangential_complex_ { typename K::Scalar_product_d inner_pdct = k.scalar_product_d_object(); typename K::Difference_of_vectors_d diff_vec = k.difference_of_vectors_d_object(); + Vector u = v; + for (int j = 0 ; j < basis.size() ; ++j) + { + Vector const& ej = basis[j]; + Vector u_proj = scaled_vec(ej, inner_pdct(u, ej) / inner_pdct(ej, ej)); + u = diff_vec(u, u_proj); + } + + FT sqlen_new_v = k.squared_length_d_object()(u); + bool add_it = (sqlen_new_v > sqlen_threshold); + if (add_it) + { + Vector new_v = scaled_vec(u, FT(1)/CGAL::sqrt(sqlen_new_v)); + + // If new_v is small, run the Gram-Schmidt once more to + // re-orthogonalize it + if (sqlen_new_v < 0.01) + { + for (int j = 0 ; j < basis.size() ; ++j) + { + Vector const& ej = basis[j]; + Vector new_v_proj = scaled_vec( + ej, inner_pdct(new_v, ej) / inner_pdct(ej, ej)); + new_v = diff_vec(new_v, new_v_proj); + } + sqlen_new_v = k.squared_length_d_object()(new_v); + new_v = scaled_vec(new_v, FT(1)/CGAL::sqrt(sqlen_new_v)); + } + +#ifdef CGAL_ALPHA_TC + if (add_to_thickening_vectors) + basis.add_thickening_vector(new_v); + else +#endif + basis.push_back(new_v); + } + return add_it; + } + + template + Basis compute_gram_schmidt_basis(Basis const& input_basis, K const& k) + { + typedef Basis Basis; + Basis output_basis(input_basis.origin()); + // Add vector one by one typename Basis::const_iterator inb_it = input_basis.begin(); typename Basis::const_iterator inb_it_end = input_basis.end(); for (int i = 0 ; inb_it != inb_it_end ; ++inb_it, ++i) - { - Vector u = *inb_it; - - for (int j = 0 ; j < i ; ++j) - { - Vector const& ej = input_basis[j]; - Vector u_proj = scaled_vec(ej, inner_pdct(u, ej) / inner_pdct(ej, ej)); - u = diff_vec(u, u_proj); - } - - output_basis.push_back(normalize_vector(u, k)); - } + add_vector_to_orthonormal_basis(output_basis, *inb_it, k); return output_basis; } diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 6f90145622e..810b5063fcd 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -375,9 +375,12 @@ std::vector generate_points_on_torus_3D( template static void generate_uniform_points_on_torus_d( - const Kernel &k, int dim, std::size_t num_slices, OutputIterator out, + const Kernel &k, int dim, std::size_t num_slices, + OutputIterator out, + double radius_noise_percentage = 0., std::vector current_point = std::vector()) { + static CGAL::Random rng; if (current_point.size() == 2*dim) { *out++ = k.construct_point_d_object()( @@ -388,24 +391,32 @@ static void generate_uniform_points_on_torus_d( { for (std::size_t slice_idx = 0 ; slice_idx < num_slices ; ++slice_idx) { + double radius_noise_ratio = 1.; + if (radius_noise_percentage > 0.) + { + radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage)/100., + (100. + radius_noise_percentage)/100.); + } std::vector cp2 = current_point; FT alpha = 6.2832 * slice_idx / num_slices; - cp2.push_back(std::cos(alpha)); - cp2.push_back(std::sin(alpha)); + cp2.push_back(radius_noise_ratio*std::cos(alpha)); + cp2.push_back(radius_noise_ratio*std::sin(alpha)); generate_uniform_points_on_torus_d( - k, dim, num_slices, out, cp2); + k, dim, num_slices, out, radius_noise_percentage, cp2); } } } template std::vector generate_points_on_torus_d( - std::size_t num_points, int dim, bool uniform = false) + std::size_t num_points, int dim, bool uniform = false, + double radius_noise_percentage = 0.) { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; Kernel k; - CGAL::Random rng; + static CGAL::Random rng; std::vector points; points.reserve(num_points); @@ -413,7 +424,7 @@ std::vector generate_points_on_torus_d( { std::size_t num_slices = (std::size_t)std::pow(num_points, 1./dim); generate_uniform_points_on_torus_d( - k, dim, num_slices, std::back_inserter(points)); + k, dim, num_slices, std::back_inserter(points), radius_noise_percentage); } else { @@ -422,13 +433,20 @@ std::vector generate_points_on_torus_d( #endif for (std::size_t i = 0 ; i < num_points ; ) { + double radius_noise_ratio = 1.; + if (radius_noise_percentage > 0.) + { + radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage)/100., + (100. + radius_noise_percentage)/100.); + } std::vector pt; pt.reserve(dim*2); for (int curdim = 0 ; curdim < dim ; ++curdim) { FT alpha = rng.get_double(0, 6.2832); - pt.push_back(std::cos(alpha)); - pt.push_back(std::sin(alpha)); + pt.push_back(radius_noise_ratio*std::cos(alpha)); + pt.push_back(radius_noise_ratio*std::sin(alpha)); } Point p = k.construct_point_d_object()(pt.begin(), pt.end()); @@ -462,7 +480,7 @@ std::vector generate_points_on_sphere_d( { Point p = *generator++; if (radius_noise_percentage > 0.) - { + { double radius_noise_ratio = rng.get_double( (100. - radius_noise_percentage)/100., (100. + radius_noise_percentage)/100.); @@ -543,68 +561,6 @@ std::vector generate_points_on_two_spheres_d( return points; } -template -std::vector -generate_points_on_two_orthogonal_spheres_d( - std::size_t num_points, int intrinsic_dim, int ambient_dim, double radius, - double distance_between_centers, double radius_noise_percentage = 0.) -{ - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Vector_d Vector; - Kernel k; - CGAL::Random rng; - CGAL::Random_points_on_sphere_d generator(dim, radius); - std::vector points; - points.reserve(num_points); - - typename Kernel::Compute_coordinate_d k_coord = - k.compute_coordinate_d_object(); - - std::vector t(dim, FT(0)); - t[0] = distance_between_centers; - Vector c1_to_c2(t.begin(), t.end()); - -#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER - Point_sparsifier > sparsifier(points); -#endif - for (std::size_t i = 0 ; i < num_points ; ) - { - Point p = *generator++; - if (radius_noise_percentage > 0.) - { - double radius_noise_ratio = rng.get_double( - (100. - radius_noise_percentage)/100., - (100. + radius_noise_percentage)/100.); - - typename Kernel::Point_to_vector_d k_pt_to_vec = - k.point_to_vector_d_object(); - typename Kernel::Vector_to_point_d k_vec_to_pt = - k.vector_to_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - k.scaled_vector_d_object(); - p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio)); - } - - std::vector pt1(ambient_dim); - for (int i = 0 ; i < intrinsic_dim ; ++i) - pt1[i] = k_coord(p, i); - // TODO : p2 - -#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER - if (sparsifier.try_to_insert_point(p)) - ++i; - if (sparsifier.try_to_insert_point(p2)) - ++i; -#else - points.push_back(p); - points.push_back(p2); - i += 2; -#endif - } - return points; -} - // Product of a 3-sphere and a circle => d = 3 / D = 5 template std::vector generate_points_on_3sphere_and_circle( From 63a5536699cb158bb0a38eedd94d7caffa25074c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 25 Jun 2015 11:36:45 +0200 Subject: [PATCH 310/487] Bugfix in RTd: in dimension 2, the points were never hidden (cherry picked from commit fa3b2d9bea15726247b3214ef25fa41f00b0fa08) --- .../include/CGAL/Regular_triangulation.h | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index b6bcdc072b0..df144d9c4cf 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -111,7 +111,6 @@ public: using Base::rotate_rotor; using Base::infinite_vertex; using Base::insert_in_hole; - using Base::insert_outside_convex_hull_1; using Base::is_infinite; using Base::locate; using Base::points_begin; @@ -269,7 +268,9 @@ public: CGAL_assertion( Vertex_handle() != hint ); return insert(p, hint->full_cell()); } - + + Vertex_handle insert_outside_convex_hull_1( + const Weighted_point & p, Full_cell_handle s); Vertex_handle insert_outside_affine_hull(const Weighted_point &); Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, @@ -826,7 +827,7 @@ Regular_triangulation typename RTTraits::Point_weight_d pw = geom_traits().point_weight_d_object(); - if (pw(p) == pw(v->point())) + if (pw(p) = pw(v->point())) return v; // If dim == 0 and the new point has a bigger weight, // we replace the point @@ -842,22 +843,49 @@ Regular_triangulation // !NO break here! } default: - if( 1 == current_dimension() ) - { - if( Base::OUTSIDE_CONVEX_HULL == lt ) - { - return insert_outside_convex_hull_1(p, s); - } - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - return v; - } + if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) + return insert_outside_convex_hull_1(p, s); else return insert_in_conflicting_cell(p, s); break; } } +// NOT DOCUMENTED... +template < class RTTraits, class TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation +::insert_outside_convex_hull_1(const Weighted_point & p, Full_cell_handle s) +{ + // This is a special case for dimension 1, because in that case, the right + // infinite full_cell is not correctly oriented... (sice its first vertex is the + // infinite one... + + bool in_conflict = is_in_conflict(p, s); + + // If p is not in conflict with s, then p is hidden + // => we don't insert it + if (!in_conflict) + { + m_hidden_points.push_back(p); + return Vertex_handle(); + } + else + { + CGAL_precondition( is_infinite(s) ); + CGAL_precondition( 1 == current_dimension() ); + int inf_v_index = s->index(infinite_vertex()); + bool swap = (0 == s->neighbor(inf_v_index)->index(s)); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + if( swap ) + { + s->swap_vertices(0, 1); + } + return v; + } +} + template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation @@ -918,21 +946,15 @@ Regular_triangulation } default: { - if( 1 == current_dimension() ) + if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) { if (s->has_vertex(star_center)) - { - if( Base::OUTSIDE_CONVEX_HULL == lt ) - { return insert_outside_convex_hull_1(p, s); - } - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - return v; - } } else + { return insert_in_conflicting_cell(p, s, star_center); + } break; } } @@ -949,22 +971,7 @@ Regular_triangulation { typedef std::vector Full_cell_h_vector; - bool in_conflict; - if( current_dimension() < maximal_dimension() ) - { - Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), - power_test_in_flat_predicate()); - in_conflict = c(s); - } - else - { - Orientation_d ori = geom_traits().orientation_d_object(); - Power_test_d side = geom_traits().power_test_d_object(); - Conflict_pred_in_fullspace c(*this, p, ori, side); - in_conflict = c(s); - } + bool in_conflict = is_in_conflict(p, s); // If p is not in conflict with s, then p is hidden // => we don't insert it @@ -1068,7 +1075,7 @@ bool Regular_triangulation ::is_in_conflict(const Weighted_point & p, Full_cell_const_handle s) const { - CGAL_precondition( 2 <= current_dimension() ); + CGAL_precondition( 1 <= current_dimension() ); if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( @@ -1092,7 +1099,7 @@ typename Regular_triangulation::Facet Regular_triangulation ::compute_conflict_zone(const Weighted_point & p, const Full_cell_handle s, OutputIterator out) const { - CGAL_precondition( 2 <= current_dimension() ); + CGAL_precondition( 1 <= current_dimension() ); if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( From ef9b73ca2e0bf3477bd38bda4f6a336cadb8f13d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 25 Jun 2015 20:35:50 +0200 Subject: [PATCH 311/487] Bugfix: == (cherry picked from commit aa81039e071bb587593c5f6c7ad3f9c2a096b84e) --- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index df144d9c4cf..531a1e15dce 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -827,7 +827,7 @@ Regular_triangulation typename RTTraits::Point_weight_d pw = geom_traits().point_weight_d_object(); - if (pw(p) = pw(v->point())) + if (pw(p) == pw(v->point())) return v; // If dim == 0 and the new point has a bigger weight, // we replace the point From 752a5550be16641caabefae8dd560d006f1de818 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 26 Jun 2015 10:10:46 +0200 Subject: [PATCH 312/487] Renamed a few variables/functions --- .../Tangential_complex/benchmark_script.txt | 4 +- .../Tangential_complex/benchmark_tc.cpp | 2 +- .../include/CGAL/Tangential_complex.h | 54 +++++++++---------- .../CGAL/Tangential_complex/utilities.h | 6 +-- .../Tangential_complex/test_utilities.cpp | 8 +-- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 26ad4eaead0..7e243e29c03 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -2,7 +2,7 @@ # Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- -#---------------------------------------------------------------- Adaptive alpha TC tests ------------------------------------------------------------------------ +#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ #generate_sphere_d 1 1 - 50 2 1 0.005 N Y N 3 1 #OK #generate_torus_d N - - 15 2 1 0.05 N Y N 10 1 #generate_sphere_d 0.302 3 - 50 3 2 0.005 N Y N 60 1 #OK @@ -16,7 +16,7 @@ generate_torus_d N 1 - 50 4 2 0.05 N Y N 3 1 # #generate_two_spheres_d 3 4 - 500 3 2 0.05 N Y N 10 1 #OK #generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N Y N 60 1 -#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ +#---------------------------------------------------------------- Fixed-alpha TC tests ------------------------------------------------------------------------ #generate_sphere_d 0.302 - - 70 2 1 0.005 N N N 60 1 #generate_sphere_d 0.304 0 - 100 3 2 0.05 N N N 60 1 #generate_sphere_d 3 0 - 100 4 3 0.05 N N N 60 1 diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 556208e190e..5751f421a14 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -407,7 +407,7 @@ void make_tc(std::vector &points, t.reset(); // Try to solve the remaining inconstencies #ifdef CGAL_ALPHA_TC - tc.solve_inconsistencies_using_adaptive_alpha_TC(); + tc.solve_inconsistencies_using_alpha_TC(); #else tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); #endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8eb77e4866d..7deef326a04 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -228,7 +228,7 @@ private: typedef std::vector Star; typedef std::vector Stars_container; - // For the priority queues of solve_inconsistencies_using_adaptive_alpha_TC + // For the priority queues of solve_inconsistencies_using_alpha_TC struct Simplex_and_alpha { Simplex_and_alpha() {} @@ -852,14 +852,14 @@ private: } public: - void solve_inconsistencies_using_adaptive_alpha_TC() + void solve_inconsistencies_using_alpha_TC() { #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif #ifdef CGAL_TC_VERBOSE - std::cerr << "Fixing inconsistencies using adaptive alpha TC..." << std::endl; + std::cerr << "Fixing inconsistencies using alpha TC..." << std::endl; #endif //------------------------------------------------------------------------- @@ -948,7 +948,7 @@ public: if (!is_simplex_in_star(saa.m_center_point_index, saa.m_simplex)) { std::cerr - << "FAILED in solve_inconsistencies_using_adaptive_alpha_TC(): " + << "FAILED in solve_inconsistencies_using_alpha_TC(): " << "the simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); @@ -983,7 +983,7 @@ public: // CJTODO TEMP else { - std::cerr << "SUCCESS in solve_inconsistencies_using_adaptive_alpha_TC(): " + std::cerr << "SUCCESS in solve_inconsistencies_using_alpha_TC(): " << "the simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); @@ -1857,7 +1857,7 @@ next_face: m_k.squared_length_d_object(); typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Scalar_product_d inner_pdct = + typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); typename Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); @@ -1967,7 +1967,7 @@ next_face: //Vector n = m_k.point_to_vector_d_object()(p); //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); - //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; + //std::cerr << "IP = " << scalar_pdct(n, ts[0]) << " & " << scalar_pdct(n, ts[1]) << std::endl; return tsb; @@ -1981,8 +1981,8 @@ next_face: //Vector t2(32., 5., 85.); //Tangent_space_basis ts; //ts.reserve(m_intrinsic_dim); - //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); - //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); + //ts.push_back(diff_vec(t1, scaled_vec(n, scalar_pdct(t1, n)))); + //ts.push_back(diff_vec(t2, scaled_vec(n, scalar_pdct(t2, n)))); //ts = compute_gram_schmidt_basis(ts, m_k); //return ts; */ @@ -2064,7 +2064,7 @@ next_face: Tr_bare_point project_point(const Point &p, const Tangent_space_basis &tsb) const { - typename Kernel::Scalar_product_d inner_pdct = + typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); @@ -2076,8 +2076,8 @@ next_face: coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { - // Local coords are given by the inner product with the vectors of tsb - FT coord = inner_pdct(v, tsb[i]); + // Local coords are given by the scalar product with the vectors of tsb + FT coord = scalar_pdct(v, tsb[i]); coords.push_back(coord); } @@ -2085,7 +2085,7 @@ next_face: Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); for (int i = 0 ; i < tv.size() ; ++i) { - FT coord = inner_pdct(v, tv[i].vec); + FT coord = scalar_pdct(v, tv[i].vec); coords.push_back(coord); } #endif @@ -2112,7 +2112,7 @@ next_face: const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); - typename Kernel::Scalar_product_d inner_pdct = + typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); @@ -2133,8 +2133,8 @@ next_face: coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { - // Local coords are given by the inner product with the vectors of tsb - FT c = inner_pdct(v, tsb[i]); + // Local coords are given by the scalar product with the vectors of tsb + FT c = scalar_pdct(v, tsb[i]); coords.push_back(c); // p_proj += c * tsb[i] @@ -2147,7 +2147,7 @@ next_face: Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); for (int i = 0 ; i < tv.size() ; ++i) { - FT c = inner_pdct(v, tv[i].vec); + FT c = scalar_pdct(v, tv[i].vec); coords.push_back(c); // p_proj += c * tv[i].vec @@ -2804,7 +2804,7 @@ next_face: m_k.squared_distance_d_object(); typename Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - typename Kernel::Scalar_product_d k_inner_pdct = + typename Kernel::Scalar_product_d k_scalar_pdct = m_k.scalar_product_d_object(); typename Kernel::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); @@ -2983,9 +2983,9 @@ next_face: compute_perturbed_point(q_idx), compute_perturbed_point(p_idx)); pq = k_scaled_vec(pq, FT(1)/sqrt(k_sqlen(pq))); FT dot_product_1 = std::abs( - k_inner_pdct(m_orth_spaces[p_idx][0], pq)); + k_scalar_pdct(m_orth_spaces[p_idx][0], pq)); FT dot_product_2 = std::abs( - k_inner_pdct(m_orth_spaces[q_idx][0], pq)); + k_scalar_pdct(m_orth_spaces[q_idx][0], pq)); csv_stream << inside_pt_indices.size() << " ; "; csv_stream << dot_product_1 << " ; " << dot_product_2; csv_stream << std::endl; @@ -3008,7 +3008,7 @@ next_face: for ( ; it_v != inconsistent_simplex.end() ; ++it_v) { FT dot_products_between_normals = - k_inner_pdct(m_tangent_spaces[i1][0], m_tangent_spaces[*it_v][0]); + k_scalar_pdct(m_tangent_spaces[i1][0], m_tangent_spaces[*it_v][0]); std::cerr << dot_products_between_normals << ", "; //csv_stream << " ; " < - bool does_voronoi_face_and_alpha_tangent_subspace_intersect( + bool does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( std::size_t center_pt_index, Indexed_point_range_a const& P, Indexed_point_range_b const& Q, diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index c58b628fe5d..f4b74119850 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -262,14 +262,14 @@ namespace Tangential_complex_ { // Kernel functors typename K::Scaled_vector_d scaled_vec = k.scaled_vector_d_object(); - typename K::Scalar_product_d inner_pdct = k.scalar_product_d_object(); + typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); typename K::Difference_of_vectors_d diff_vec = k.difference_of_vectors_d_object(); Vector u = v; for (int j = 0 ; j < basis.size() ; ++j) { Vector const& ej = basis[j]; - Vector u_proj = scaled_vec(ej, inner_pdct(u, ej) / inner_pdct(ej, ej)); + Vector u_proj = scaled_vec(ej, scalar_pdct(u, ej) / scalar_pdct(ej, ej)); u = diff_vec(u, u_proj); } @@ -287,7 +287,7 @@ namespace Tangential_complex_ { { Vector const& ej = basis[j]; Vector new_v_proj = scaled_vec( - ej, inner_pdct(new_v, ej) / inner_pdct(ej, ej)); + ej, scalar_pdct(new_v, ej) / scalar_pdct(ej, ej)); new_v = diff_vec(new_v, new_v_proj); } sqlen_new_v = k.squared_length_d_object()(new_v); diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.cpp b/Tangential_complex/test/Tangential_complex/test_utilities.cpp index f902cca8f08..85d1646cecf 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.cpp +++ b/Tangential_complex/test/Tangential_complex/test_utilities.cpp @@ -37,16 +37,16 @@ void test_does_voronoi_face_and_alpha_tangent_subspace_intersect() osb.push_back(Vec(0.01, 0.995)); - assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( points, 0, P, Q, osb, 0.0, k) == false); - assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( points, 0, P, Q, osb, 0.5, k) == false); - assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( points, 0, P, Q, osb, 1.0, k) == false); - assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( points, 0, P, Q, osb, 1.5, k) == true); } From d7be58c3099f121adc791e19471b1f233f4249a2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 30 Jun 2015 17:51:33 +0200 Subject: [PATCH 313/487] Fixed a bug in Gram-Schmidt We were not taking thickening vectors into account --- .../CGAL/Tangential_complex/utilities.h | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index f4b74119850..1c8956382cf 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -224,9 +224,27 @@ namespace Tangential_complex_ { const FT MARGIN = 0.001; // CJTODO TEMP FT alpha_i = k_scalar_pdct(it_v->vec, vec); if (alpha_i + MARGIN > it_v->alpha_plus) + { +#ifdef CGAL_TC_VERY_VERBOSE + std::cerr << "OLD alpha+ = " << it_v->alpha_plus << std::endl; +#endif it_v->alpha_plus = alpha_i + MARGIN; +#ifdef CGAL_TC_VERY_VERBOSE + std::cerr << "NEW alpha+ = " << it_v->alpha_plus << std::endl; + std::cerr << "NOT MODIFIED alpha- = " << it_v->alpha_minus << std::endl; +#endif + } else if (alpha_i - MARGIN < it_v->alpha_minus) + { +#ifdef CGAL_TC_VERY_VERBOSE + std::cerr << "OLD alpha- = " << it_v->alpha_minus << std::endl; +#endif it_v->alpha_minus = alpha_i - MARGIN; +#ifdef CGAL_TC_VERY_VERBOSE + std::cerr << "NEW alpha- = " << it_v->alpha_minus << std::endl; + std::cerr << "NOT MODIFIED alpha+ = " << it_v->alpha_plus << std::endl; +#endif + } } } @@ -272,6 +290,12 @@ namespace Tangential_complex_ { Vector u_proj = scaled_vec(ej, scalar_pdct(u, ej) / scalar_pdct(ej, ej)); u = diff_vec(u, u_proj); } + for (int j = 0 ; j < basis.num_thickening_vectors() ; ++j) + { + Vector const& ej = basis.thickening_vectors()[j].vec; + Vector u_proj = scaled_vec(ej, scalar_pdct(u, ej) / scalar_pdct(ej, ej)); + u = diff_vec(u, u_proj); + } FT sqlen_new_v = k.squared_length_d_object()(u); bool add_it = (sqlen_new_v > sqlen_threshold); @@ -290,6 +314,13 @@ namespace Tangential_complex_ { ej, scalar_pdct(new_v, ej) / scalar_pdct(ej, ej)); new_v = diff_vec(new_v, new_v_proj); } + for (int j = 0 ; j < basis.num_thickening_vectors() ; ++j) + { + Vector const& ej = basis.thickening_vectors()[j].vec; + Vector new_v_proj = scaled_vec( + ej, scalar_pdct(new_v, ej) / scalar_pdct(ej, ej)); + new_v = diff_vec(new_v, new_v_proj); + } sqlen_new_v = k.squared_length_d_object()(new_v); new_v = scaled_vec(new_v, FT(1)/CGAL::sqrt(sqlen_new_v)); } From fab4c9d5a81bfab393ea3a1d728a50cdb105ae84 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 30 Jun 2015 17:55:29 +0200 Subject: [PATCH 314/487] More debugging code --- .../include/CGAL/Tangential_complex.h | 42 +++++++++++++++++-- .../include/CGAL/Tangential_complex/config.h | 1 + 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7deef326a04..8de84e1c86b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -952,14 +952,15 @@ public: << "the simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << "was not added in the star\n"; + std::cerr << "was not added in the star #" + << saa.m_center_point_index << "\n"; Indexed_simplex full_s = saa.m_simplex; full_s.insert(saa.m_center_point_index); // CJTODO TEMP bool is_this_simplex_somewhere = false; - for(auto ii : saa.m_simplex) + for(auto ii : saa.m_simplex) // CJTODO C++11 { Indexed_simplex z = full_s; z.erase(ii); @@ -978,7 +979,41 @@ public: std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; else std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; - + + std::cerr << "Checking simplices of the star #" + << saa.m_center_point_index << std::endl; + Star const& star = m_stars[saa.m_center_point_index]; + for (Star::const_iterator is = star.begin(), is_end = star.end() ; + is != is_end ; ++is) + { + if (is_simplex_in_the_ambient_delaunay(*is)) + std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + else + { + std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + for(auto ii : *is) // CJTODO C++11 + perturb(ii); + } + } + + std::cerr << "Perturbing the points..." << std::endl; + perturb(saa.m_center_point_index); + for(auto ii : saa.m_simplex) // CJTODO C++11 + perturb(ii); + refresh_tangential_complex(); + pqueues.clear(); + pqueues.resize(m_ambient_dim - m_intrinsic_dim + 1); + + std::size_t num_inconsistent_simplices = 0; + // For each triangulation + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + num_inconsistent_simplices += fill_pqueues_for_alpha_tc(i, pqueues); + +#ifdef CGAL_TC_VERBOSE + std::cerr + << "Num inconsistent simplices found when filling the priority queues: " + << num_inconsistent_simplices << std::endl; +#endif } // CJTODO TEMP else @@ -988,6 +1023,7 @@ public: std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); std::cerr << "was successfully added in the star\n"; + //check_if_all_simplices_are_in_the_ambient_delaunay(); } #endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 9c26f718d30..3f01cde07a4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -39,6 +39,7 @@ //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE +#define CGAL_TC_VERY_VERBOSE #define CGAL_TC_PERFORM_EXTRA_CHECKS //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES //#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM From e8e5f7e43818ccf84cbdd925c33a8b3d1da3558c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 1 Jul 2015 15:53:19 +0200 Subject: [PATCH 315/487] More detailed trace --- Tangential_complex/include/CGAL/Tangential_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8de84e1c86b..ec3b7926815 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1022,7 +1022,8 @@ public: << "the simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << "was successfully added in the star\n"; + std::cerr << "was successfully added in the star #" + << saa.m_center_point_index << "\n"; //check_if_all_simplices_are_in_the_ambient_delaunay(); } #endif From f015159ff05ceffe12b1aad44056a646e8ae2c18 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 1 Jul 2015 15:53:59 +0200 Subject: [PATCH 316/487] Use a 0.1% margin instead of a fixed offset --- .../include/CGAL/Tangential_complex/utilities.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 1c8956382cf..8dc54e557a1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -221,25 +221,25 @@ namespace Tangential_complex_ { it_v_end = m_thickening_vectors.end() ; it_v != it_v_end ; ++it_v) { - const FT MARGIN = 0.001; // CJTODO TEMP + const FT MARGIN_RATIO = 1.001; // CJTODO TEMP FT alpha_i = k_scalar_pdct(it_v->vec, vec); - if (alpha_i + MARGIN > it_v->alpha_plus) + if (alpha_i * MARGIN_RATIO > it_v->alpha_plus) { #ifdef CGAL_TC_VERY_VERBOSE std::cerr << "OLD alpha+ = " << it_v->alpha_plus << std::endl; #endif - it_v->alpha_plus = alpha_i + MARGIN; + it_v->alpha_plus = alpha_i * MARGIN_RATIO; #ifdef CGAL_TC_VERY_VERBOSE std::cerr << "NEW alpha+ = " << it_v->alpha_plus << std::endl; std::cerr << "NOT MODIFIED alpha- = " << it_v->alpha_minus << std::endl; #endif } - else if (alpha_i - MARGIN < it_v->alpha_minus) + else if (alpha_i * MARGIN_RATIO < it_v->alpha_minus) { #ifdef CGAL_TC_VERY_VERBOSE std::cerr << "OLD alpha- = " << it_v->alpha_minus << std::endl; #endif - it_v->alpha_minus = alpha_i - MARGIN; + it_v->alpha_minus = alpha_i * MARGIN_RATIO; #ifdef CGAL_TC_VERY_VERBOSE std::cerr << "NEW alpha- = " << it_v->alpha_minus << std::endl; std::cerr << "NOT MODIFIED alpha+ = " << it_v->alpha_plus << std::endl; From 48b8382de3a5ecf066ba0c4de083540314d59c84 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 6 Jul 2015 19:04:29 +0200 Subject: [PATCH 317/487] Definitely removed the "infinite vertex at position 0" constraint... ... and fixed the regular triangulation at the same time. Even though this constraint had been dropped, the code was still expecting the infinite vertex to be at position 0 in the cells. Now, it's not the case anymore, the infinite vertex can be anywhere. This is particularly useful for the 2D case, because the constraint made the orientation of the "rightmost" infinite cell wrong. --- .../include/CGAL/Delaunay_triangulation.h | 61 ++++++---- .../include/CGAL/Regular_triangulation.h | 114 +++++------------- Triangulation/include/CGAL/Triangulation.h | 30 +++-- .../CGAL/Triangulation_data_structure.h | 8 +- .../test/Triangulation/test_delaunay.cpp | 6 +- .../test/Triangulation/test_regular.cpp | 3 +- 6 files changed, 94 insertions(+), 128 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index a1c8015bb3e..ac27605c6e0 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -365,24 +365,14 @@ Delaunay_triangulation return Full_cell_handle(); } Full_cell_handle left = v->full_cell(); - if( is_infinite(left) && left->neighbor(0)->index(left) == 0 ) // we are on the infinite right. - left = left->neighbor(0); if( 0 == left->index(v) ) left = left->neighbor(1); CGAL_assertion( 1 == left->index(v) ); Full_cell_handle right = left->neighbor(0); - if( ! is_infinite(right) ) - { - tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); - set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); - } - else - { - tds().associate_vertex_with_full_cell(left, 1, left->vertex(0)); - tds().associate_vertex_with_full_cell(left, 0, infinite_vertex()); - set_neighbors(left, 0, left->neighbor(1), left->mirror_index(1)); - set_neighbors(left, 1, right->neighbor(1), right->mirror_index(1)); - } + + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); + tds().delete_vertex(v); tds().delete_full_cell(right); return left; @@ -471,24 +461,16 @@ Delaunay_triangulation { int v_idx = (*it)->index(v); tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); - if( v_idx != 0 ) - { - // we must put the infinite vertex at index 0. - // OK, now with the new convention that the infinite vertex - // does not have to be at index 0, this is not necessary, - // but still, I prefer to keep this piece of code here. [-- Samuel Hornus] - (*it)->swap_vertices(0, v_idx); - // Now, we preserve the positive orientation of the full_cell - (*it)->swap_vertices(current_dimension() - 1, current_dimension()); - } } // Make the handles to infinite full cells searchable infinite_simps.make_searchable(); // Then, modify the neighboring relation for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) { - for( int i = 1; i <= current_dimension(); ++i ) + for( int i = 0; i <= current_dimension(); ++i ) { + if (is_infinite((*it)->vertex(i))) + continue; (*it)->vertex(i)->set_full_cell(*it); Full_cell_handle n = (*it)->neighbor(i); // Was |n| a finite full cell prior to removing |v| ? @@ -732,6 +714,35 @@ Delaunay_triangulation CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) reorient_full_cells(); + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + // Otherwise, let's find the right infinite cell + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + } + } } return v; } diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 02efd84268c..7d23dfa0f83 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -242,7 +242,7 @@ public: Facet ft; Full_cell_handle c = locate (*p, lt, f, ft, hint); Vertex_handle v = insert (*p, lt, f, ft, c); - + hint = v == Vertex_handle() ? c : v->full_cell(); } return number_of_vertices() - n; @@ -269,9 +269,7 @@ public: CGAL_assertion( Vertex_handle() != hint ); return insert(p, hint->full_cell()); } - - Vertex_handle insert_outside_convex_hull_1( - const Weighted_point & p, Full_cell_handle s); + Vertex_handle insert_outside_affine_hull(const Weighted_point &); Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, @@ -494,24 +492,12 @@ Regular_triangulation return Full_cell_handle(); } Full_cell_handle left = v->full_cell(); - if( is_infinite(left) && left->neighbor(0)->index(left) == 0 ) // we are on the infinite right. - left = left->neighbor(0); if( 0 == left->index(v) ) left = left->neighbor(1); CGAL_assertion( 1 == left->index(v) ); Full_cell_handle right = left->neighbor(0); - if( ! is_infinite(right) ) - { - tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); - set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); - } - else - { - tds().associate_vertex_with_full_cell(left, 1, left->vertex(0)); - tds().associate_vertex_with_full_cell(left, 0, infinite_vertex()); - set_neighbors(left, 0, left->neighbor(1), left->mirror_index(1)); - set_neighbors(left, 1, right->neighbor(1), right->mirror_index(1)); - } + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); tds().delete_vertex(v); tds().delete_full_cell(right); return left; @@ -604,24 +590,16 @@ Regular_triangulation { int v_idx = (*it)->index(v); tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); - if( v_idx != 0 ) - { - // we must put the infinite vertex at index 0. - // OK, now with the new convention that the infinite vertex - // does not have to be at index 0, this is not necessary, - // but still, I prefer to keep this piece of code here. [-- Samuel Hornus] - (*it)->swap_vertices(0, v_idx); - // Now, we preserve the positive orientation of the full_cell - (*it)->swap_vertices(current_dimension() - 1, current_dimension()); - } } // Make the handles to infinite full cells searchable infinite_simps.make_searchable(); // Then, modify the neighboring relation for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) { - for( int i = 1; i <= current_dimension(); ++i ) + for( int i = 0 ; i <= current_dimension(); ++i ) { + if (is_infinite((*it)->vertex(i))) + continue; (*it)->vertex(i)->set_full_cell(*it); Full_cell_handle n = (*it)->neighbor(i); // Was |n| a finite full cell prior to removing |v| ? @@ -844,46 +822,7 @@ Regular_triangulation // !NO break here! } default: - if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) - return insert_outside_convex_hull_1(p, s); - else - return insert_in_conflicting_cell(p, s); - break; - } -} - -// NOT DOCUMENTED... -template < class RTTraits, class TDS > -typename Regular_triangulation::Vertex_handle -Regular_triangulation -::insert_outside_convex_hull_1(const Weighted_point & p, Full_cell_handle s) -{ - // This is a special case for dimension 1, because in that case, the right - // infinite full_cell is not correctly oriented... (sice its first vertex is the - // infinite one... - - bool in_conflict = is_in_conflict(p, s); - - // If p is not in conflict with s, then p is hidden - // => we don't insert it - if (!in_conflict) - { - m_hidden_points.push_back(p); - return Vertex_handle(); - } - else - { - CGAL_precondition( is_infinite(s) ); - CGAL_precondition( 1 == current_dimension() ); - int inf_v_index = s->index(infinite_vertex()); - bool swap = (0 == s->neighbor(inf_v_index)->index(s)); - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - if( swap ) - { - s->swap_vertices(0, 1); - } - return v; + return insert_in_conflicting_cell(p, s); } } @@ -908,6 +847,30 @@ Regular_triangulation CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) reorient_full_cells(); + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); + } + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); + } + } + } } return v; } @@ -946,18 +909,7 @@ Regular_triangulation // !NO break here! } default: - { - if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) - { - if (s->has_vertex(star_center)) - return insert_outside_convex_hull_1(p, s); - } - else - { - return insert_in_conflicting_cell(p, s, star_center); - } - break; - } + return insert_in_conflicting_cell(p, s, star_center); } return Vertex_handle(); diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 2dee695b77a..d18df57a282 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -756,6 +756,21 @@ protected: } }; + void display_all_full_cells__debugging() + { + std::cerr << "ALL FULL CELLS:" << std::endl; + for (Full_cell_const_iterator cit = full_cells_begin() ; + cit != full_cells_end() ; ++cit ) + { + std::cerr << std::hex << &*cit << ": "; + for (int jj = 0 ; jj <= current_dimension() ; ++jj) + std::cerr << (is_infinite(cit->vertex(jj)) ? 0xFFFFFFFF : (unsigned int)&*cit->vertex(jj)) << " - "; + std::cerr << std::dec << std::endl; + } + std::cerr << std::endl; + } + + }; // Triangulation<...> // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = @@ -769,17 +784,15 @@ Triangulation { if( current_dimension() < 1 ) return; + Full_cell_iterator sit = full_cells_begin(); Full_cell_iterator send = full_cells_end(); - while( sit != send ) + for ( ; sit != send ; ++sit) { - if( is_infinite(sit) && (1 == current_dimension()) ) + if( ! (is_infinite(sit) && (1 == current_dimension())) ) { - ++sit; - continue; + sit->swap_vertices(current_dimension() - 1, current_dimension()); } - sit->swap_vertices(current_dimension() - 1, current_dimension()); - ++sit; } } @@ -901,13 +914,8 @@ Triangulation CGAL_precondition( is_infinite(s) ); CGAL_precondition( 1 == current_dimension() ); int inf_v_index = s->index(infinite_vertex()); - bool swap = (0 == s->neighbor(inf_v_index)->index(s)); Vertex_handle v = tds().insert_in_full_cell(s); v->set_point(p); - if( swap ) - { - s->swap_vertices(0, 1); - } return v; } diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 895a6f11b51..aab42e68b84 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -894,8 +894,7 @@ Triangulation_data_structure if( v_idx != current_dimension() ) { (*it)->swap_vertices(v_idx, current_dimension()); - if( ( ! (*it)->has_vertex(star) ) || (current_dimension() > 2) ) - (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); + (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); } (*it)->set_vertex(current_dimension(), Vertex_handle()); (*it)->set_neighbor(current_dimension(), Full_cell_handle()); @@ -1144,11 +1143,6 @@ void Triangulation_data_structure for( int k = 1; k <= cur_dim; ++k ) associate_vertex_with_full_cell(S_new, k, vertex(S, k - 1)); } - else if( cur_dim == 2 ) - { // if cur. dim. is 2, we must take care of the 'rightmost' infinite vertex. - if( S->mirror_index(S->index(star)) == 0 ) - swap_me = S; - } } // now we setup the neighbors set_visited(start, false); diff --git a/Triangulation/test/Triangulation/test_delaunay.cpp b/Triangulation/test/Triangulation/test_delaunay.cpp index 3b98f66660d..98b75431ca4 100644 --- a/Triangulation/test/Triangulation/test_delaunay.cpp +++ b/Triangulation/test/Triangulation/test_delaunay.cpp @@ -117,10 +117,10 @@ int main(int argc, char **argv) if( argc > 1 ) N = atoi(argv[1]); //go<5>(N); - //go<4>(N); - //go<3>(N); + go<4>(N); + go<3>(N); go<2>(N); - //go<1>(N); + go<1>(N); cerr << endl; return 0; diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index d1a6c568777..01aa6d957c5 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -123,9 +123,10 @@ int main(int argc, char **argv) if( argc > 1 ) N = atoi(argv[1]); //go<5>(N); - //go<4>(N); + go<4>(N); go<3>(N); go<2>(N); + go<1>(N); cerr << endl; return 0; From 5531f6f169789a3f2fa5eafa06aefdc2a95a9804 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 6 Jul 2015 19:04:29 +0200 Subject: [PATCH 318/487] Definitely removed the "infinite vertex at position 0" constraint... ... and fixed the regular triangulation at the same time. Even though this constraint had been dropped, the code was still expecting the infinite vertex to be at position 0 in the cells. Now, it's not the case anymore, the infinite vertex can be anywhere. This is particularly useful for the 2D case, because the constraint made the orientation of the "rightmost" infinite cell wrong. (cherry picked from commit 48b8382de3a5ecf066ba0c4de083540314d59c84) --- .../include/CGAL/Delaunay_triangulation.h | 61 ++++++---- .../include/CGAL/Regular_triangulation.h | 114 +++++------------- Triangulation/include/CGAL/Triangulation.h | 30 +++-- .../CGAL/Triangulation_data_structure.h | 8 +- .../test/Triangulation/test_delaunay.cpp | 6 +- .../test/Triangulation/test_regular.cpp | 3 +- 6 files changed, 94 insertions(+), 128 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 75eabc243e0..30fe8d6c1b5 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -363,24 +363,14 @@ Delaunay_triangulation return Full_cell_handle(); } Full_cell_handle left = v->full_cell(); - if( is_infinite(left) && left->neighbor(0)->index(left) == 0 ) // we are on the infinite right. - left = left->neighbor(0); if( 0 == left->index(v) ) left = left->neighbor(1); CGAL_assertion( 1 == left->index(v) ); Full_cell_handle right = left->neighbor(0); - if( ! is_infinite(right) ) - { - tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); - set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); - } - else - { - tds().associate_vertex_with_full_cell(left, 1, left->vertex(0)); - tds().associate_vertex_with_full_cell(left, 0, infinite_vertex()); - set_neighbors(left, 0, left->neighbor(1), left->mirror_index(1)); - set_neighbors(left, 1, right->neighbor(1), right->mirror_index(1)); - } + + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); + tds().delete_vertex(v); tds().delete_full_cell(right); return left; @@ -469,24 +459,16 @@ Delaunay_triangulation { int v_idx = (*it)->index(v); tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); - if( v_idx != 0 ) - { - // we must put the infinite vertex at index 0. - // OK, now with the new convention that the infinite vertex - // does not have to be at index 0, this is not necessary, - // but still, I prefer to keep this piece of code here. [-- Samuel Hornus] - (*it)->swap_vertices(0, v_idx); - // Now, we preserve the positive orientation of the full_cell - (*it)->swap_vertices(current_dimension() - 1, current_dimension()); - } } // Make the handles to infinite full cells searchable infinite_simps.make_searchable(); // Then, modify the neighboring relation for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) { - for( int i = 1; i <= current_dimension(); ++i ) + for( int i = 0; i <= current_dimension(); ++i ) { + if (is_infinite((*it)->vertex(i))) + continue; (*it)->vertex(i)->set_full_cell(*it); Full_cell_handle n = (*it)->neighbor(i); // Was |n| a finite full cell prior to removing |v| ? @@ -730,6 +712,35 @@ Delaunay_triangulation CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) reorient_full_cells(); + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + // Otherwise, let's find the right infinite cell + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + } + } } return v; } diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 531a1e15dce..c9d8f027663 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -241,7 +241,7 @@ public: Facet ft; Full_cell_handle c = locate (*p, lt, f, ft, hint); Vertex_handle v = insert (*p, lt, f, ft, c); - + hint = v == Vertex_handle() ? c : v->full_cell(); } return number_of_vertices() - n; @@ -268,9 +268,7 @@ public: CGAL_assertion( Vertex_handle() != hint ); return insert(p, hint->full_cell()); } - - Vertex_handle insert_outside_convex_hull_1( - const Weighted_point & p, Full_cell_handle s); + Vertex_handle insert_outside_affine_hull(const Weighted_point &); Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, @@ -493,24 +491,12 @@ Regular_triangulation return Full_cell_handle(); } Full_cell_handle left = v->full_cell(); - if( is_infinite(left) && left->neighbor(0)->index(left) == 0 ) // we are on the infinite right. - left = left->neighbor(0); if( 0 == left->index(v) ) left = left->neighbor(1); CGAL_assertion( 1 == left->index(v) ); Full_cell_handle right = left->neighbor(0); - if( ! is_infinite(right) ) - { - tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); - set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); - } - else - { - tds().associate_vertex_with_full_cell(left, 1, left->vertex(0)); - tds().associate_vertex_with_full_cell(left, 0, infinite_vertex()); - set_neighbors(left, 0, left->neighbor(1), left->mirror_index(1)); - set_neighbors(left, 1, right->neighbor(1), right->mirror_index(1)); - } + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); tds().delete_vertex(v); tds().delete_full_cell(right); return left; @@ -603,24 +589,16 @@ Regular_triangulation { int v_idx = (*it)->index(v); tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); - if( v_idx != 0 ) - { - // we must put the infinite vertex at index 0. - // OK, now with the new convention that the infinite vertex - // does not have to be at index 0, this is not necessary, - // but still, I prefer to keep this piece of code here. [-- Samuel Hornus] - (*it)->swap_vertices(0, v_idx); - // Now, we preserve the positive orientation of the full_cell - (*it)->swap_vertices(current_dimension() - 1, current_dimension()); - } } // Make the handles to infinite full cells searchable infinite_simps.make_searchable(); // Then, modify the neighboring relation for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) { - for( int i = 1; i <= current_dimension(); ++i ) + for( int i = 0 ; i <= current_dimension(); ++i ) { + if (is_infinite((*it)->vertex(i))) + continue; (*it)->vertex(i)->set_full_cell(*it); Full_cell_handle n = (*it)->neighbor(i); // Was |n| a finite full cell prior to removing |v| ? @@ -843,46 +821,7 @@ Regular_triangulation // !NO break here! } default: - if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) - return insert_outside_convex_hull_1(p, s); - else - return insert_in_conflicting_cell(p, s); - break; - } -} - -// NOT DOCUMENTED... -template < class RTTraits, class TDS > -typename Regular_triangulation::Vertex_handle -Regular_triangulation -::insert_outside_convex_hull_1(const Weighted_point & p, Full_cell_handle s) -{ - // This is a special case for dimension 1, because in that case, the right - // infinite full_cell is not correctly oriented... (sice its first vertex is the - // infinite one... - - bool in_conflict = is_in_conflict(p, s); - - // If p is not in conflict with s, then p is hidden - // => we don't insert it - if (!in_conflict) - { - m_hidden_points.push_back(p); - return Vertex_handle(); - } - else - { - CGAL_precondition( is_infinite(s) ); - CGAL_precondition( 1 == current_dimension() ); - int inf_v_index = s->index(infinite_vertex()); - bool swap = (0 == s->neighbor(inf_v_index)->index(s)); - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - if( swap ) - { - s->swap_vertices(0, 1); - } - return v; + return insert_in_conflicting_cell(p, s); } } @@ -907,6 +846,30 @@ Regular_triangulation CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) reorient_full_cells(); + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); + } + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); + } + } + } } return v; } @@ -945,18 +908,7 @@ Regular_triangulation // !NO break here! } default: - { - if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) - { - if (s->has_vertex(star_center)) - return insert_outside_convex_hull_1(p, s); - } - else - { - return insert_in_conflicting_cell(p, s, star_center); - } - break; - } + return insert_in_conflicting_cell(p, s, star_center); } return Vertex_handle(); diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 2dee695b77a..d18df57a282 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -756,6 +756,21 @@ protected: } }; + void display_all_full_cells__debugging() + { + std::cerr << "ALL FULL CELLS:" << std::endl; + for (Full_cell_const_iterator cit = full_cells_begin() ; + cit != full_cells_end() ; ++cit ) + { + std::cerr << std::hex << &*cit << ": "; + for (int jj = 0 ; jj <= current_dimension() ; ++jj) + std::cerr << (is_infinite(cit->vertex(jj)) ? 0xFFFFFFFF : (unsigned int)&*cit->vertex(jj)) << " - "; + std::cerr << std::dec << std::endl; + } + std::cerr << std::endl; + } + + }; // Triangulation<...> // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = @@ -769,17 +784,15 @@ Triangulation { if( current_dimension() < 1 ) return; + Full_cell_iterator sit = full_cells_begin(); Full_cell_iterator send = full_cells_end(); - while( sit != send ) + for ( ; sit != send ; ++sit) { - if( is_infinite(sit) && (1 == current_dimension()) ) + if( ! (is_infinite(sit) && (1 == current_dimension())) ) { - ++sit; - continue; + sit->swap_vertices(current_dimension() - 1, current_dimension()); } - sit->swap_vertices(current_dimension() - 1, current_dimension()); - ++sit; } } @@ -901,13 +914,8 @@ Triangulation CGAL_precondition( is_infinite(s) ); CGAL_precondition( 1 == current_dimension() ); int inf_v_index = s->index(infinite_vertex()); - bool swap = (0 == s->neighbor(inf_v_index)->index(s)); Vertex_handle v = tds().insert_in_full_cell(s); v->set_point(p); - if( swap ) - { - s->swap_vertices(0, 1); - } return v; } diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index f6097292c13..5fdec606642 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -888,8 +888,7 @@ Triangulation_data_structure if( v_idx != current_dimension() ) { (*it)->swap_vertices(v_idx, current_dimension()); - if( ( ! (*it)->has_vertex(star) ) || (current_dimension() > 2) ) - (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); + (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); } (*it)->set_vertex(current_dimension(), Vertex_handle()); (*it)->set_neighbor(current_dimension(), Full_cell_handle()); @@ -1138,11 +1137,6 @@ void Triangulation_data_structure for( int k = 1; k <= cur_dim; ++k ) associate_vertex_with_full_cell(S_new, k, vertex(S, k - 1)); } - else if( cur_dim == 2 ) - { // if cur. dim. is 2, we must take care of the 'rightmost' infinite vertex. - if( S->mirror_index(S->index(star)) == 0 ) - swap_me = S; - } } // now we setup the neighbors set_visited(start, false); diff --git a/Triangulation/test/Triangulation/test_delaunay.cpp b/Triangulation/test/Triangulation/test_delaunay.cpp index 3b98f66660d..98b75431ca4 100644 --- a/Triangulation/test/Triangulation/test_delaunay.cpp +++ b/Triangulation/test/Triangulation/test_delaunay.cpp @@ -117,10 +117,10 @@ int main(int argc, char **argv) if( argc > 1 ) N = atoi(argv[1]); //go<5>(N); - //go<4>(N); - //go<3>(N); + go<4>(N); + go<3>(N); go<2>(N); - //go<1>(N); + go<1>(N); cerr << endl; return 0; diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index d1a6c568777..01aa6d957c5 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -123,9 +123,10 @@ int main(int argc, char **argv) if( argc > 1 ) N = atoi(argv[1]); //go<5>(N); - //go<4>(N); + go<4>(N); go<3>(N); go<2>(N); + go<1>(N); cerr << endl; return 0; From 35555fd3f99dfca0b344670f7f2645e5ca90130f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 6 Jul 2015 19:45:59 +0200 Subject: [PATCH 319/487] Forgot to fix Triangulation accordingly (see previous commit) --- Triangulation/include/CGAL/Triangulation.h | 32 ++++++++++++++++++- .../test/Triangulation/test_triangulation.cpp | 9 +++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index d18df57a282..dc3df8adc0c 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -756,7 +756,7 @@ protected: } }; - void display_all_full_cells__debugging() + void display_all_full_cells__debugging() const { std::cerr << "ALL FULL CELLS:" << std::endl; for (Full_cell_const_iterator cit = full_cells_begin() ; @@ -971,6 +971,36 @@ Triangulation CGAL_assertion( COPLANAR != o ); if( NEGATIVE == o ) reorient_full_cells(); + + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + // Otherwise, let's find the right infinite cell + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + } + } } return v; } diff --git a/Triangulation/test/Triangulation/test_triangulation.cpp b/Triangulation/test/Triangulation/test_triangulation.cpp index f6230bf4250..f48b261f28e 100644 --- a/Triangulation/test/Triangulation/test_triangulation.cpp +++ b/Triangulation/test/Triangulation/test_triangulation.cpp @@ -114,10 +114,11 @@ int main(int argc, char **argv) int N = 1000; if( argc > 1 ) N = atoi(argv[1]); - //go<5>(N); - //go<3>(N); - go<2>(N); - //go<1>(N); + //go<5>(N); + go<4>(N); + go<3>(N); + go<2>(N); + go<1>(N); cerr << std::endl; return 0; From 2c1f647107f46041a4c8ad0498fe7a4244a4d370 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 6 Jul 2015 19:45:59 +0200 Subject: [PATCH 320/487] Forgot to fix Triangulation accordingly (see previous commit) (cherry picked from commit 35555fd3f99dfca0b344670f7f2645e5ca90130f) --- Triangulation/include/CGAL/Triangulation.h | 32 ++++++++++++++++++- .../test/Triangulation/test_triangulation.cpp | 9 +++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index d18df57a282..dc3df8adc0c 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -756,7 +756,7 @@ protected: } }; - void display_all_full_cells__debugging() + void display_all_full_cells__debugging() const { std::cerr << "ALL FULL CELLS:" << std::endl; for (Full_cell_const_iterator cit = full_cells_begin() ; @@ -971,6 +971,36 @@ Triangulation CGAL_assertion( COPLANAR != o ); if( NEGATIVE == o ) reorient_full_cells(); + + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + // Otherwise, let's find the right infinite cell + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + } + } } return v; } diff --git a/Triangulation/test/Triangulation/test_triangulation.cpp b/Triangulation/test/Triangulation/test_triangulation.cpp index f6230bf4250..f48b261f28e 100644 --- a/Triangulation/test/Triangulation/test_triangulation.cpp +++ b/Triangulation/test/Triangulation/test_triangulation.cpp @@ -114,10 +114,11 @@ int main(int argc, char **argv) int N = 1000; if( argc > 1 ) N = atoi(argv[1]); - //go<5>(N); - //go<3>(N); - go<2>(N); - //go<1>(N); + //go<5>(N); + go<4>(N); + go<3>(N); + go<2>(N); + go<1>(N); cerr << std::endl; return 0; From 3e1a2e86691f487d065723c089356cfd13c600e2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 7 Jul 2015 09:18:16 +0200 Subject: [PATCH 321/487] Call set_error_behaviour to ease debugging --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 5751f421a14..cf67335779e 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -533,6 +533,8 @@ void make_tc(std::vector &points, int main() { + CGAL::set_error_behaviour(CGAL::ABORT); + #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG int num_threads = 1; From b88286122fca9194f8ea6aa6b3f9d0b2dacc7073 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 7 Jul 2015 09:19:12 +0200 Subject: [PATCH 322/487] Don't build ambient Delaunay if dim is too high --- .../test/Tangential_complex/test_tangential_complex.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 9ac1d555c5c..c632a9e4b11 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -100,7 +100,8 @@ int main() tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - tc.check_if_all_simplices_are_in_the_ambient_delaunay(); + if (ambient_dim <= 4) + tc.check_if_all_simplices_are_in_the_ambient_delaunay(); double export_before_time = -1.; if (INTRINSIC_DIMENSION <= 3) From 8418c6178d9531066d89a62beb1b5066528f8404 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 7 Jul 2015 09:20:36 +0200 Subject: [PATCH 323/487] Verbose output --- .../include/CGAL/Tangential_complex.h | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ec3b7926815..84a7691e0a0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1396,7 +1396,11 @@ private: // other threads are perturbing the positions const Point center_pt = compute_perturbed_point(i); Tangent_space_basis &tsb = m_tangent_spaces[i]; - + +#if defined(CGAL_TC_VERY_VERBOSE) && defined(CGAL_ALPHA_TC) + std::cerr << "Base dimension, incl. thickening vectors: " + << tsb.dimension() << std::endl; +#endif // Estimate the tangent space if (!m_are_tangent_spaces_computed[i]) { @@ -1465,6 +1469,10 @@ private: if (verbose) std::cerr << "* Inserted point #" << i << std::endl; +#ifdef CGAL_TC_VERY_VERBOSE + std::size_t num_attempts_to_insert_points = 1; + std::size_t num_inserted_points = 1; +#endif //const int NUM_NEIGHBORS = 150; //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); @@ -1500,11 +1508,18 @@ private: Tr_point proj_pt = project_point_and_compute_weight( neighbor_pt, neighbor_weight, tsb, local_tr_traits); + +#ifdef CGAL_TC_VERY_VERBOSE + ++num_attempts_to_insert_points; +#endif Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); //Tr_vertex_handle vh = local_tr.insert(proj_pt); if (vh != Tr_vertex_handle()) { +#ifdef CGAL_TC_VERY_VERBOSE + ++num_inserted_points; +#endif if (verbose) std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; @@ -1568,7 +1583,11 @@ private: } } } - + +#ifdef CGAL_TC_VERY_VERBOSE + std::cerr << "Inserted " << num_inserted_points << " points / " + << num_attempts_to_insert_points << " attemps to compute the star\n"; +#endif #ifdef CGAL_ALPHA_TC if (tsb.num_thickening_vectors() == 0) update_star__no_thickening_vectors(i); From c92ca5ff47ebc5ae87147a7f77295594cce0c571 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 7 Jul 2015 16:03:59 +0200 Subject: [PATCH 324/487] Renamed test_utilities.h to avoid confusion --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 2 +- Tangential_complex/test/Tangential_complex/aniso_TC.cpp | 2 +- .../test/Tangential_complex/test_tangential_complex.cpp | 2 +- .../{test_utilities.h => testing_utilities.h} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename Tangential_complex/test/Tangential_complex/{test_utilities.h => testing_utilities.h} (100%) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index cf67335779e..b90dce674e4 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -12,7 +12,7 @@ #include #include -#include "../../test/Tangential_complex/test_utilities.h" +#include "../../test/Tangential_complex/testing_utilities.h" #include #include diff --git a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp index 147411ee2e5..6983311773a 100644 --- a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp +++ b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp @@ -3,7 +3,7 @@ #include #include -#include "../../test/Tangential_complex/test_utilities.h" +#include "../../test/Tangential_complex/testing_utilities.h" #include // Anisotropic metrics #include diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index c632a9e4b11..f94f004a504 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -12,7 +12,7 @@ #include #include -#include "test_utilities.h" +#include "testing_utilities.h" #include #include diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/testing_utilities.h similarity index 100% rename from Tangential_complex/test/Tangential_complex/test_utilities.h rename to Tangential_complex/test/Tangential_complex/testing_utilities.h From d5ef993d30c2e028e25b9332ee883aa95dc91bbf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Jul 2015 17:08:05 +0200 Subject: [PATCH 325/487] Fix warnings + timers + minor changes --- .../include/CGAL/Tangential_complex.h | 114 ++++++++++++------ .../CGAL/Tangential_complex/utilities.h | 29 +++++ 2 files changed, 106 insertions(+), 37 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 84a7691e0a0..596de6d390f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -415,8 +415,8 @@ public: m_k.compute_coordinate_d_object(); std::vector sum_eigen_values(m_ambient_dim, FT(0)); - std::size_t num_points_for_pca = - std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim); + std::size_t num_points_for_pca = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -426,6 +426,7 @@ public: const Point &p = *it_p; KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); + //******************************* PCA ************************************* // One row = one point @@ -656,7 +657,7 @@ public: for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { // Don't export infinite cells - if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + if (is_infinite(*it_inc_simplex)) continue; Indexed_simplex c = *it_inc_simplex; @@ -704,8 +705,7 @@ public: for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { // Don't export infinite cells - if (!export_infinite_simplices && *it_inc_simplex->rbegin() - == std::numeric_limits::max()) + if (!export_infinite_simplices && is_infinite(*it_inc_simplex)) continue; Indexed_simplex c = *it_inc_simplex; @@ -785,7 +785,7 @@ private: Incident_simplex const& s = *it_inc_simplex; // Don't check infinite cells - if (*s.rbegin() == std::numeric_limits::max()) + if (is_infinite(s)) continue; int simplex_dim = static_cast(s.size()); @@ -869,6 +869,10 @@ public: std::vector, std::greater > AATC_pq; typedef std::vector PQueues; + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_pq; +#endif // One queue per dimension, from intrinsic dim (index = 0) to // ambiant dim (index = ambiant - intrinsic dim) @@ -883,7 +887,11 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Num inconsistent simplices found when filling the priority queues: " - << num_inconsistent_simplices << std::endl; + << num_inconsistent_simplices; +# ifdef CGAL_TC_PROFILING + std::cerr << " (" << t_pq.elapsed() << " s)" << std::endl; +# endif + std::cerr << std::endl; #endif //------------------------------------------------------------------------- @@ -893,6 +901,10 @@ public: // While there's elements to treat in the queues for(;;) { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_one_fix; +#endif + // Pick the simplex with the lowest dimension and the lowest alpha Simplex_and_alpha saa; bool found_saa = false; @@ -949,11 +961,16 @@ public: { std::cerr << "FAILED in solve_inconsistencies_using_alpha_TC(): " - << "the simplex " << saa.m_center_point_index << ", "; + << "simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << "was not added in the star #" - << saa.m_center_point_index << "\n"; + std::cerr << " not added in star #" + << saa.m_center_point_index + << " (basis dim = " << tangent_basis.dimension() +# ifdef CGAL_TC_PROFILING + << " - " << t_one_fix.elapsed() << " s" +# endif + << ")\n"; Indexed_simplex full_s = saa.m_simplex; full_s.insert(saa.m_center_point_index); @@ -975,24 +992,27 @@ public: std::cerr << "WOW The simplex is NOWHERE!\n"; // CJTODO TEMP - if (is_simplex_in_the_ambient_delaunay(full_s)) - std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; - else - std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; - - std::cerr << "Checking simplices of the star #" - << saa.m_center_point_index << std::endl; - Star const& star = m_stars[saa.m_center_point_index]; - for (Star::const_iterator is = star.begin(), is_end = star.end() ; - is != is_end ; ++is) - { - if (is_simplex_in_the_ambient_delaunay(*is)) + if (m_ambient_dim <= 3) + { + if (is_simplex_in_the_ambient_delaunay(full_s)) std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; else - { std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; - for(auto ii : *is) // CJTODO C++11 - perturb(ii); + + std::cerr << "Checking simplices of the star #" + << saa.m_center_point_index << std::endl; + Star const& star = m_stars[saa.m_center_point_index]; + for (Star::const_iterator is = star.begin(), is_end = star.end() ; + is != is_end ; ++is) + { + if (is_simplex_in_the_ambient_delaunay(*is)) + std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + else + { + std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + for(auto ii : *is) // CJTODO C++11 + perturb(ii); + } } } @@ -1018,12 +1038,17 @@ public: // CJTODO TEMP else { - std::cerr << "SUCCESS in solve_inconsistencies_using_alpha_TC(): " - << "the simplex " << saa.m_center_point_index << ", "; + std::cerr << "SUCCESS: " + << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << "was successfully added in the star #" - << saa.m_center_point_index << "\n"; + std::cerr << " added in star #" + << saa.m_center_point_index + << " (basis dim = " << tangent_basis.dimension() +# ifdef CGAL_TC_PROFILING + << " - " << t_one_fix.elapsed() << " s" +# endif + << ")\n"; //check_if_all_simplices_are_in_the_ambient_delaunay(); } #endif @@ -1136,7 +1161,7 @@ public: ++it_inc_simplex) { // Skip infinite cells - if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + if (is_infinite(*it_inc_simplex)) continue; Indexed_simplex c = *it_inc_simplex; @@ -1386,6 +1411,11 @@ private: }; #endif // CGAL_LINKED_WITH_TBB + bool is_infinite(Indexed_simplex const& s) const + { + return *s.rbegin() == std::numeric_limits::max(); + } + void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) @@ -1443,6 +1473,8 @@ private: local_tr_traits.point_weight_d_object(); typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); //*************************************************** @@ -1488,6 +1520,12 @@ private: nn_it != ins_range.end() ; ++nn_it) { +#ifdef CGAL_ALPHA_TC + ++number_of_attempts_to_insert_points; + if (number_of_attempts_to_insert_points > MAX_NUM_INSERTED_POINTS) + break; +#endif + std::size_t neighbor_point_idx = nn_it->first; // ith point = p, which is already inserted @@ -1512,6 +1550,7 @@ private: #ifdef CGAL_TC_VERY_VERBOSE ++num_attempts_to_insert_points; #endif + Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); //Tr_vertex_handle vh = local_tr.insert(proj_pt); @@ -1592,7 +1631,10 @@ private: if (tsb.num_thickening_vectors() == 0) update_star__no_thickening_vectors(i); else + { update_star__with_thickening_vector(i); + //check_if_all_simplices_are_in_the_ambient_delaunay(); // CJTODO TEMP + } #else update_star__no_thickening_vectors(i); #endif @@ -2564,7 +2606,7 @@ next_face: const Incident_simplex &incident_simplex = *it_inc_simplex; // Don't check infinite cells - if (*incident_simplex.rbegin() == std::numeric_limits::max()) + if (is_infinite(incident_simplex)) continue; Indexed_simplex c = incident_simplex; @@ -3185,8 +3227,7 @@ next_face: bool inconsistencies_found = false; // Don't check infinite simplices - if (*incident_simplex.rbegin() - == std::numeric_limits::max()) + if (is_infinite(incident_simplex)) return false; Indexed_simplex simplex = incident_simplex; @@ -3697,8 +3738,7 @@ next_face: for ( ; it_simplex != it_simplex_end ; ++it_simplex) { // Don't export infinite cells - if (*it_simplex->first.rbegin() - == std::numeric_limits::max()) + if (is_infinite(it_simplex->first)) continue; const Indexed_simplex &c = it_simplex->first; @@ -3876,7 +3916,7 @@ public: for ( ; it_tri != it_tri_end ; ++it_tri) { // Don't export infinite cells - if (*it_tri->rbegin() == std::numeric_limits::max()) + if (is_infinite(*it_tri)) continue; os << 3 << " "; @@ -3947,7 +3987,7 @@ public: for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { // Don't check infinite cells - if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + if (is_infinite(*it_inc_simplex)) continue; Indexed_simplex c = *it_inc_simplex; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 8dc54e557a1..ec95a318317 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -248,6 +248,35 @@ namespace Tangential_complex_ { } } + FT alpha_minus(std::size_t i) const + { + return m_thickening_vectors[i].alpha_minus; + } + FT alpha_plus(std::size_t i) const + { + return m_thickening_vectors[i].alpha_plus; + } + + // Returns 0 if no thickening vectors + FT max_absolute_alpha() const + { + FT max = FT(0); + + for (Thickening_vectors::const_iterator + it_v = m_thickening_vectors.begin(), + it_v_end = m_thickening_vectors.end() ; + it_v != it_v_end ; + ++it_v) + { + if (it_v->alpha_plus > max) + max = it_v->alpha_plus; + if (-it_v->alpha_minus > max) + max = -it_v->alpha_minus; + } + + return max; + } + int dimension() const { return static_cast(m_vectors.size() + m_thickening_vectors.size()); From 761d776252338dfdc979c8a959bf79adbf5b2c71 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Jul 2015 17:09:41 +0200 Subject: [PATCH 326/487] Use the stars instead of the local triangulations for the export --- .../include/CGAL/Tangential_complex.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 596de6d390f..d080deef7cc 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1297,7 +1297,19 @@ public: Simplex_range stars_simplices; if (!p_complex) { - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + Stars_container::const_iterator it_star = m_stars.begin(); + Stars_container::const_iterator it_star_end = m_stars.end(); + // For each star: get the finite simplices + for ( ; it_star != it_star_end ; ++it_star) + { + for (Star::const_iterator it_s = it_star->begin(), + it_s_end = it_star->end() ; it_s != it_s_end ; ++it_s) + { + if (!is_infinite(*it_s)) + stars_simplices.insert(*it_s); + } + } + /*typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) @@ -1326,7 +1338,7 @@ public: stars_simplices.insert(simplex); } - } + }*/ p_simplices = &stars_simplices; } From 909dd40233dec7357fe879527f46713371d48b79 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Jul 2015 17:13:31 +0200 Subject: [PATCH 327/487] Forgot the commit variable declaration (fix commit d5ef993) --- Tangential_complex/include/CGAL/Tangential_complex.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d080deef7cc..eba7bce121a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1526,6 +1526,18 @@ private: // and which contains all the // circumspheres of the star of "center_vertex" boost::optional squared_star_sphere_radius_plus_margin; + +#ifdef CGAL_ALPHA_TC + /*FT max_absolute_alpha = tsb.max_absolute_alpha(); + // "2*m_half_sparsity" because both points can be perturbed + FT max_sqdist_to_tangent_space = (max_absolute_alpha == FT(0) ? + FT(0) : CGAL::square(2*max_absolute_alpha + 2*m_half_sparsity));*/ + std::size_t number_of_attempts_to_insert_points = 0; + const std::size_t MAX_NUM_INSERTED_POINTS = + tsb.num_thickening_vectors() > 0 ? + static_cast(std::pow(4, /*tsb.dimension()*/m_intrinsic_dim)) + : std::numeric_limits::max(); +#endif // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; From fd265e1e4f99162048c5eb6385347f5222602ac1 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 21 Jul 2015 18:02:16 +0200 Subject: [PATCH 328/487] Missing const --- Triangulation/include/CGAL/Triangulation_data_structure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 5fdec606642..6cdc3f4d48e 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -611,7 +611,7 @@ public: return incident_faces(v, dim, out, cmp, true); } template< typename OutputIterator, typename Comparator = std::less > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); + OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false) const; #else template< typename OutputIterator, typename Comparator > OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator()) From d5c3c0bf918f2474f5cb937e46b6a19313dcbd99 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 21 Jul 2015 19:24:10 +0200 Subject: [PATCH 329/487] Benchmark comparing Td vs T2/T3 --- .../benchmark/Triangulation/CMakeLists.txt | 1 + .../Triangulation/Td_vs_T2_and_T3.cpp | 113 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp diff --git a/Triangulation/benchmark/Triangulation/CMakeLists.txt b/Triangulation/benchmark/Triangulation/CMakeLists.txt index 9529aed0791..97c0fe9b2db 100644 --- a/Triangulation/benchmark/Triangulation/CMakeLists.txt +++ b/Triangulation/benchmark/Triangulation/CMakeLists.txt @@ -21,6 +21,7 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") include_directories (BEFORE "include") create_single_source_cgal_program( "delaunay.cpp" ) + create_single_source_cgal_program( "Td_vs_T2_and_T3.cpp" ) else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") diff --git a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp new file mode 100644 index 00000000000..3bd077f0cad --- /dev/null +++ b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp @@ -0,0 +1,113 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +template +void test(int d, int N, std::string const& DTd_static_or_dyn) +{ + unsigned int seed = static_cast(time(NULL)); + std::cerr << "Delaunay triangulation of " << N << " points in dim " << d; + + // Td + { + typedef typename DTd::Point Point; + typedef CGAL::Random_points_in_cube_d Random_points_iterator; + + CGAL::default_random = CGAL::Random(seed); + std::vector points; + Random_points_iterator rand_it(d, 2.0); + CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); + + DTd dt(d); + CGAL::Timer timer; + timer.start(); + dt.insert(points.begin(), points.end()); + + std::cerr << " * Td: " << timer.time() << " s." << std::endl; + std::size_t nbfc = dt.number_of_finite_full_cells(); + std::size_t nbc = dt.number_of_full_cells(); + std::cerr << " " << dt.number_of_vertices() << " vertices, " + << nbfc << " finite simplices and " + << (nbc - nbfc) << " convex hull Facets." + << std::endl; + } + + // T2 or T3 + { + typedef typename DT_23::Point Point_23; + CGAL::default_random = CGAL::Random(seed); // Same seed + std::vector points; + RPI_23 rand_it(2.0); + CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); + + CGAL::Timer timer; + timer.start(); + + DT_23 dt; + dt.insert(points.begin(), points.end()); + + std::cerr << " * T" << d << ": " << timer.time() << " s." << std::endl; + /*std::size_t nbfc = dt.number_of_finite_full_cells(); + std::size_t nbc = dt.number_of_full_cells(); + std::cerr << " " << dt.number_of_vertices() << " vertices, " + << nbfc << " finite simplices and " + << (nbc - nbfc) << " convex hull Facets." + << std::endl;*/ + } + +} + +template< int D > +void go(const int N) +{ + CGAL_assertion(D == 2 || D == 3); + + // Td + //typedef CGAL::Epick_d > Kd; + typedef CGAL::Epick_d Kd; + typedef CGAL::Delaunay_triangulation DTd; + + // T2 or T3 + typedef CGAL::Exact_predicates_inexact_constructions_kernel K23; + if (D == 2) + { + typedef CGAL::Delaunay_triangulation_2 DT_2; + typedef typename DT_2::Point Point; + typedef CGAL::Random_points_in_square_2 RPI_2; + test(D, N, "static"); + } + else if (D == 3) + { + typedef CGAL::Delaunay_triangulation_3 DT_3; + typedef typename DT_3::Point Point; + typedef CGAL::Random_points_in_cube_3 RPI_3; + test(D, N, "static"); + } +} + +int main(int argc, char **argv) +{ + srand(static_cast(time(NULL))); +#ifdef _DEBUG + int N = 100; +#else + int N = 100000; +#endif + if (argc > 1) N = atoi(argv[1]); + go<2>(N); + go<3>(N); + + return 0; +} From c0d2bbe2bb4d414376bc45ca5d54e06264f00fb9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 23 Jul 2015 14:50:00 +0200 Subject: [PATCH 330/487] Benchmark now compares Delaunay and Regular triangulations --- .../Triangulation/Td_vs_T2_and_T3.cpp | 233 ++++++++++++++---- 1 file changed, 190 insertions(+), 43 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp index 3bd077f0cad..ba9933849f4 100644 --- a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp +++ b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp @@ -1,9 +1,18 @@ #include #include +#include +#include #include +#include +#include +#include +#include + #include #include +#include +#include #include #include @@ -13,87 +22,215 @@ #include #include +template +struct Stats_getter; -template -void test(int d, int N, std::string const& DTd_static_or_dyn) +// T2 specialization +template +struct Stats_getter > { - unsigned int seed = static_cast(time(NULL)); - std::cerr << "Delaunay triangulation of " << N << " points in dim " << d; + typedef CGAL::Delaunay_triangulation_2 DT; + Stats_getter(DT const& dt) : m_dt(dt) {} + + std::size_t number_of_vertices() { return m_dt.number_of_vertices(); } + std::size_t number_of_finite_cells() { return m_dt.number_of_faces(); } + + DT m_dt; +}; + +// RT2 specialization +template +struct Stats_getter > +{ + typedef CGAL::Regular_triangulation_2 DT; + + Stats_getter(DT const& dt) : m_dt(dt) {} + + std::size_t number_of_vertices() { return m_dt.number_of_vertices(); } + std::size_t number_of_finite_cells() { return m_dt.number_of_faces(); } + + DT m_dt; +}; + +// T3 specialization +template +struct Stats_getter > +{ + typedef CGAL::Delaunay_triangulation_3 DT; + + Stats_getter(DT const& dt) : m_dt(dt) {} + + std::size_t number_of_vertices() { return m_dt.number_of_vertices(); } + std::size_t number_of_finite_cells() { return m_dt.number_of_finite_cells(); } + + DT m_dt; +}; + +// RT3 specialization +template +struct Stats_getter > +{ + typedef CGAL::Regular_triangulation_3 DT; + + Stats_getter(DT const& dt) : m_dt(dt) {} + + std::size_t number_of_vertices() { return m_dt.number_of_vertices(); } + std::size_t number_of_finite_cells() { return m_dt.number_of_finite_cells(); } + + DT m_dt; +}; + + +template +void test( + int d, int N, Pt_d_range const& points_d, Pt_23_range const& points_23, + std::string const& DTd_static_or_dyn) +{ // Td { - typedef typename DTd::Point Point; - typedef CGAL::Random_points_in_cube_d Random_points_iterator; - - CGAL::default_random = CGAL::Random(seed); - std::vector points; - Random_points_iterator rand_it(d, 2.0); - CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); - - DTd dt(d); + DT_d dt(d); CGAL::Timer timer; timer.start(); - dt.insert(points.begin(), points.end()); + dt.insert(points_d.begin(), points_d.end()); std::cerr << " * Td: " << timer.time() << " s." << std::endl; - std::size_t nbfc = dt.number_of_finite_full_cells(); - std::size_t nbc = dt.number_of_full_cells(); std::cerr << " " << dt.number_of_vertices() << " vertices, " - << nbfc << " finite simplices and " - << (nbc - nbfc) << " convex hull Facets." + << dt.number_of_finite_full_cells() << " finite cells." << std::endl; } // T2 or T3 { - typedef typename DT_23::Point Point_23; - CGAL::default_random = CGAL::Random(seed); // Same seed - std::vector points; - RPI_23 rand_it(2.0); - CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); - CGAL::Timer timer; timer.start(); DT_23 dt; - dt.insert(points.begin(), points.end()); + dt.insert(points_23.begin(), points_23.end()); std::cerr << " * T" << d << ": " << timer.time() << " s." << std::endl; - /*std::size_t nbfc = dt.number_of_finite_full_cells(); - std::size_t nbc = dt.number_of_full_cells(); - std::cerr << " " << dt.number_of_vertices() << " vertices, " - << nbfc << " finite simplices and " - << (nbc - nbfc) << " convex hull Facets." - << std::endl;*/ + Stats_getter sg(dt); + std::cerr << " " << sg.number_of_vertices() << " vertices, " + << sg.number_of_finite_cells() << " finite cells." + << std::endl; } - } -template< int D > +template< int D, typename Dim_tag > void go(const int N) { CGAL_assertion(D == 2 || D == 3); - // Td - //typedef CGAL::Epick_d > Kd; - typedef CGAL::Epick_d Kd; - typedef CGAL::Delaunay_triangulation DTd; + // Generate points (in a common "array" format) + std::vector > coords; + coords.reserve(N); + for (int i = 0; i < N; ++i) + { + CGAL::cpp11::array pt; + for (int j = 0; j < D; ++j) + pt[j] = CGAL::default_random.get_double(-1., 1.); + coords.push_back(pt); + } + // Generate weights + std::vector weights; + weights.reserve(N); + for (int i = 0; i < N; ++i) + weights.push_back(CGAL::default_random.get_double(-10., 10.)); + + // DTd + typedef CGAL::Epick_d Kd; + typedef CGAL::Delaunay_triangulation DT_d; + typedef typename DT_d::Point Point_d; + + std::vector points_d; + points_d.reserve(N); + for (int i = 0; i < N; ++i) + points_d.push_back(Point_d(D, coords[i].begin(), coords[i].end())); + + // RTd + typedef CGAL::Regular_triangulation_euclidean_traits Traits_d; + typedef CGAL::Regular_triangulation RT_d; + typedef typename RT_d::Bare_point Bare_point_d; + typedef typename RT_d::Point WPoint_d; + + std::vector wpoints_d; + wpoints_d.reserve(N); + for (int i = 0; i < N; ++i) + { + wpoints_d.push_back(WPoint_d( + Bare_point_d(D, coords[i].begin(), coords[i].end()), + weights[i])); + } // T2 or T3 typedef CGAL::Exact_predicates_inexact_constructions_kernel K23; if (D == 2) { + // Delaunay typedef CGAL::Delaunay_triangulation_2 DT_2; typedef typename DT_2::Point Point; - typedef CGAL::Random_points_in_square_2 RPI_2; - test(D, N, "static"); + + std::vector points; + points.reserve(N); + for (int i = 0; i < N; ++i) + points.push_back(Point(coords[i][0], coords[i][1])); + + std::cerr << std::endl << "DELAUNAY - dim " << D << " - " + << N << " points." << std::endl; + test(D, N, points_d, points, "static"); + + // Regular + typedef CGAL::Regular_triangulation_filtered_traits_2 Traits_2; + typedef CGAL::Regular_triangulation_2 RT_2; + typedef typename RT_2::Bare_point Bare_point; + typedef typename RT_2::Point WPoint; + + std::vector wpoints; + wpoints.reserve(N); + for (int i = 0; i < N; ++i) + { + wpoints.push_back(WPoint( + Bare_point(coords[i][0], coords[i][1]), + weights[i])); + } + + std::cerr << std::endl << "REGULAR - dim " << D << " - " + << N << " points." << std::endl; + test(D, N, wpoints_d, wpoints, "static"); } else if (D == 3) { typedef CGAL::Delaunay_triangulation_3 DT_3; typedef typename DT_3::Point Point; - typedef CGAL::Random_points_in_cube_3 RPI_3; - test(D, N, "static"); + + std::vector points; + points.reserve(N); + for (int i = 0; i < N; ++i) + points.push_back(Point(coords[i][0], coords[i][1], coords[i][2])); + + std::cerr << std::endl << "DELAUNAY - dim " << D << " - " + << N << " points." << std::endl; + test(D, N, points_d, points, "static"); + + // Regular + typedef CGAL::Regular_triangulation_filtered_traits_3 Traits_3; + typedef CGAL::Regular_triangulation_3 RT_3; + typedef typename RT_3::Bare_point Bare_point; + typedef typename RT_3::Point WPoint; + + std::vector wpoints; + wpoints.reserve(N); + for (int i = 0; i < N; ++i) + { + wpoints.push_back(WPoint( + Bare_point(coords[i][0], coords[i][1], coords[i][2]), + weights[i])); + } + + std::cerr << std::endl << "REGULAR - dim " << D << " - " + << N << " points." << std::endl; + test(D, N, wpoints_d, wpoints, "static"); } } @@ -106,8 +243,18 @@ int main(int argc, char **argv) int N = 100000; #endif if (argc > 1) N = atoi(argv[1]); - go<2>(N); - go<3>(N); + + std::cerr << "-----------------------------------------" << std::endl; + std::cerr << "-- STATIC --" << std::endl; + std::cerr << "-----------------------------------------" << std::endl; + go<2, CGAL::Dimension_tag<2> >(N); + go<3, CGAL::Dimension_tag<3> >(N); + + std::cerr << "-----------------------------------------" << std::endl; + std::cerr << "-- DYNAMIC --" << std::endl; + std::cerr << "-----------------------------------------" << std::endl; + go<2, CGAL::Dynamic_dimension_tag>(N); + go<3, CGAL::Dynamic_dimension_tag>(N); return 0; } From 6ade6e28dffacc54352c62f0dc5febc0e0f9160a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 23 Jul 2015 17:53:46 +0200 Subject: [PATCH 331/487] Better output --- .../benchmark/Triangulation/Td_vs_T2_and_T3.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp index ba9933849f4..cd5212ca7e6 100644 --- a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp +++ b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp @@ -19,8 +19,10 @@ #include #include #include + #include #include +#include "console_color.h" template struct Stats_getter; @@ -95,7 +97,8 @@ void test( timer.start(); dt.insert(points_d.begin(), points_d.end()); - std::cerr << " * Td: " << timer.time() << " s." << std::endl; + std::cerr << " * Td: " << yellow << timer.time() << " s" + << white << std::endl; std::cerr << " " << dt.number_of_vertices() << " vertices, " << dt.number_of_finite_full_cells() << " finite cells." << std::endl; @@ -109,7 +112,8 @@ void test( DT_23 dt; dt.insert(points_23.begin(), points_23.end()); - std::cerr << " * T" << d << ": " << timer.time() << " s." << std::endl; + std::cerr << " * T" << d << ": " << yellow << timer.time() << " s" + << white << std::endl; Stats_getter sg(dt); std::cerr << " " << sg.number_of_vertices() << " vertices, " << sg.number_of_finite_cells() << " finite cells." @@ -249,12 +253,14 @@ int main(int argc, char **argv) std::cerr << "-----------------------------------------" << std::endl; go<2, CGAL::Dimension_tag<2> >(N); go<3, CGAL::Dimension_tag<3> >(N); + std::cerr << std::endl; std::cerr << "-----------------------------------------" << std::endl; std::cerr << "-- DYNAMIC --" << std::endl; std::cerr << "-----------------------------------------" << std::endl; go<2, CGAL::Dynamic_dimension_tag>(N); go<3, CGAL::Dynamic_dimension_tag>(N); + std::cerr << std::endl; return 0; } From 6bd2b58341fafdd48ee318ff56f36485019cead0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 23 Jul 2015 17:59:07 +0200 Subject: [PATCH 332/487] Forgot console_color.h --- .../benchmark/Triangulation/console_color.h | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Triangulation/benchmark/Triangulation/console_color.h diff --git a/Triangulation/benchmark/Triangulation/console_color.h b/Triangulation/benchmark/Triangulation/console_color.h new file mode 100644 index 00000000000..50554178257 --- /dev/null +++ b/Triangulation/benchmark/Triangulation/console_color.h @@ -0,0 +1,68 @@ +#ifndef CONSOLE_COLOR_H_ +#define CONSOLE_COLOR_H_ + +#include + +#if defined(WIN32) +#include +#endif + +inline std::ostream& blue(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY); +#else + s << "\x1b[0;34m"; +#endif + return s; +} + +inline std::ostream& red(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, FOREGROUND_RED|FOREGROUND_INTENSITY); +#else + s << "\x1b[0;31m"; +#endif + return s; +} + +inline std::ostream& green(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN|FOREGROUND_INTENSITY); +#else + s << "\x1b[0;32m"; +#endif + return s; +} + +inline std::ostream& yellow(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY); +#else + s << "\x1b[0;33m"; +#endif + return s; +} + +inline std::ostream& white(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); +#else + s << "\x1b[0;37m"; +#endif + return s; +} + +#endif From 235c527bab834882a0b7552c06b07014a8e2d82f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Sep 2015 15:57:15 +0200 Subject: [PATCH 333/487] Fix doc of gather_full_cells --- .../doc/Triangulation/Concepts/TriangulationDataStructure.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDataStructure.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDataStructure.h index ac2c83bc4f2..e94d15d7806 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDataStructure.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDataStructure.h @@ -257,11 +257,13 @@ The predicate must return `true` if the traversal of that `Facet` leads to a good full cell. All the good full cells are output into the last argument `out`. -\pre `start != Full_cell_handle()` and `start` is a good cell. +Returns a facet on the boundary of the set of cells. + +\pre `start != Full_cell_handle()` and `start` is a good cell. */ template< typename TraversalPredicate, typename OutputIterator > -void gather_full_cells(Full_cell_handle start, TraversalPredicate & tp, +Facet gather_full_cells(Full_cell_handle start, TraversalPredicate & tp, OutputIterator & out) const; /*! From a7a085022f7fab9db730723860396d246e47669b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Sep 2015 16:02:06 +0200 Subject: [PATCH 334/487] Added an optional #define to deactive static filters --- Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp index cd5212ca7e6..3c9bacc51cd 100644 --- a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp +++ b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp @@ -1,3 +1,6 @@ +// To deactivate statics filters in the 2D/3D case +//#define CGAL_NO_STATIC_FILTERS + #include #include #include From 45e05d5884adbc62acaafa65f32f518fac84fc5b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Sep 2015 18:49:21 +0200 Subject: [PATCH 335/487] Typos + small improvements --- .../CGAL/Delaunay_triangulation.h | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h index e62889fcf47..338e62d4b74 100644 --- a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h @@ -22,11 +22,11 @@ having all vertices of the simplex on its boundary. Parameters -------------- -`DelaunayTriangulationTraits` is the geometric traits class that provides the geometric types +\tparam DelaunayTriangulationTraits is the geometric traits class that provides the geometric types and predicates needed by Delaunay triangulations. `DelaunayTriangulationTraits` must be a model of the concept `DelaunayTriangulationTraits`. -The parameter `TriangulationDataStructure` must be a model of the concept +\tparam TriangulationDataStructure must be a model of the concept `TriangulationDataStructure`. This model is used to store the faces of the triangulation. The parameter `TriangulationDataStructure` defaults to `Triangulation_data_structure` whose template parameters are instantiated as @@ -37,15 +37,12 @@ follows:
  • `Triangulation_full_cell`.
  • -The class template `Delaunay_triangulation` can +\tparam Delaunay_triangulation can be defined by specifying only the first parameter, or by using the tag `CGAL::Default` as the second parameter. -The class `Delaunay_triangulation` inherits all the types -defined in the base class `Triangulation`. Additionally, it -defines or overloads the following methods: - -\sa `Triangulation_data_structure` +\sa `Regular_triangulation` +\sa `Triangulation_data_structure` */ template< typename DelaunayTriangulationTraits, typename TriangulationDataStructure > @@ -141,7 +138,7 @@ is called.) The parameters `lt`, `f`, `ft` and `c` must be consistent with the localization of point `p` in the Delaunay triangulation e.g. by a call to -`c = locate(p, lt, f, ft)`. +`Triangulation::locate(const Point &, Locate_type &, Face &, Vertex_handle) const`. \cgalAdvancedEnd */ Vertex_handle insert(const Point & p, const Locate_type lt, @@ -153,8 +150,7 @@ Inserts the point `p` in the Delaunay triangulation. Returns a handle to the (possibly newly created) vertex at that position. \pre The point `p` must lie outside the affine hull of the Delaunay triangulation. This implies that -`dt`.`current_dimension()` must be less that -`dt`.`maximal_dimension()`. +`dt`.`current_dimension()` must be less than `dt`.`maximal_dimension()`. \cgalAdvancedEnd */ Vertex_handle insert_outside_affine_hull(const Point & p); @@ -184,15 +180,13 @@ const; /*! \cgalAdvancedBegin -Outputs handles to the full cells in confict with +Outputs handles to the full cells in conflict with point `p` into the `OutputIterator out`. The full cell `c` is used as a starting point for gathering the full cells in conflict with `p`. A facet `(cc,i)` on the boundary of the conflict zone with `cc` in conflict is returned. -\pre `c` is in conflict -with `p`. -`dt`.`current_dimension()`\f$ \geq2\f$. +\pre `c` is in conflict with `p` and `dt`.`current_dimension()`\f$ \geq2\f$. \cgalAdvancedEnd */ template< typename OutputIterator > From 3833fe88839cd8850b0b1f4a5d14b571721c50be Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Sep 2015 18:51:00 +0200 Subject: [PATCH 336/487] Fix return type + add comments --- Triangulation/include/CGAL/Regular_triangulation.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index c9d8f027663..fda64bb9d8d 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -190,6 +190,9 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + // Warning: these functions are not correct since they do not restore hidden + // vertices + Full_cell_handle remove(Vertex_handle); Full_cell_handle remove(const Weighted_point & p, Full_cell_handle hint = Full_cell_handle()) { @@ -217,7 +220,7 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS template< typename ForwardIterator > - size_type insert(ForwardIterator start, ForwardIterator end) + std::ptrdiff_t insert(ForwardIterator start, ForwardIterator end) { size_type n = number_of_vertices(); typedef std::vector WP_vec; @@ -469,6 +472,9 @@ private: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + +// Warning: this function is not correct since it does not restore hidden +// vertices template< typename RTTraits, typename TDS > typename Regular_triangulation::Full_cell_handle Regular_triangulation From 5ecd62cf15916fc2de94d8e5204dae5e93c37fbe Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Sep 2015 18:51:17 +0200 Subject: [PATCH 337/487] Document Regular_triangulation --- .../CGAL/Regular_triangulation.h | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h new file mode 100644 index 00000000000..3602dae1773 --- /dev/null +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -0,0 +1,194 @@ + +namespace CGAL { + +/*! +\ingroup PkgTriangulationsTriangulationClasses + +This class is used to maintain the +regular triangulation -- also known as weighted Delaunay triangulation -- +of a set of weighted points in \f$ \mathbb{R}^D \f$. +The dimension \f$ D\f$ can be specified at compile-time or +run-time. It should be kept reasonably small -- see the performance +section in the user manual for what reasonable means. + +Note that the removal of points is not supported yet. + +A regular triangulation is defined as follows. + +Let \f$ {S}^{(w)}\f$ be a set of weighted points in \f$ \mathbb{R}^D\f$. Let +\f$ {p}^{(w)}=(p,w_p), p\in\mathbb{R}^D, w_p\in\mathbb{R}\f$ and +\f$ {z}^{(w)}=(z,w_z), z\in\mathbb{R}^D, w_z\in\mathbb{R}\f$ +be two weighted points. +A weighted point +\f$ {p}^{(w)}=(p,w_p)\f$ can also be seen as a sphere of center \f$ p\f$ and +radius \f$ \sqrt{w_p}\f$. +The power product (or power distance ) +between \f$ {p}^{(w)}\f$ and \f$ {z}^{(w)}\f$ is +defined as +\f[ \Pi({p}^{(w)},{z}^{(w)}) = {\|{p-z}\|^2-w_p-w_z} \f] +where \f$ \|{p-z}\|\f$ is the Euclidean distance between \f$ p\f$ and \f$ z\f$. +\f$ {p}^{(w)}\f$ and \f$ {z}^{(w)}\f$ +are said to be orthogonal if \f$ \Pi{({p}^{(w)}-{z}^{(w)})} += 0\f$. + +\f$D + 1\f$ weighted points have a unique common orthogonal weighted point +called the power sphere. A sphere \f$ {z}^{(w)}\f$ is said to be +regular if \f$ \forall {p}^{(w)}\in{S}^{(w)}, +\Pi{({p}^{(w)}-{z}^{(w)})}\geq 0\f$. + +A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres +of all simplices are regular. + +Parameters +-------------- + +\tparam RegularTriangulationTraits is the geometric traits class that provides the +geometric types and predicates needed by regular triangulations. +`RegularTriangulationTraits` must be a model of the concept +`RegularTriangulationTraits`. + +\tparam TriangulationDataStructure must be a model of the concept +`TriangulationDataStructure`. This model is used to store +the faces of the triangulation. The parameter `TriangulationDataStructure` +defaults to `Triangulation_data_structure` whose template parameters are +instantiated as follows: +
      +
    • `RegularTriangulationTraits::Dimension`
    • +
    • `Triangulation_vertex`
    • +
    • `Triangulation_full_cell`.
    • +
    + +\tparam Regular_triangulation can +be defined by specifying only the first parameter, or by using the +tag `CGAL::Default` as the second parameter. + +\sa `Delaunay_triangulation` +\sa `Triangulation_data_structure` + +*/ +template< typename RegularTriangulationTraits, typename TriangulationDataStructure > +class Regular_triangulation + : public Triangulation +{ +public: + +/// \name Types +/// @{ + +/*! +A point in Euclidean space. +*/ +typedef RegularTriangulationTraits::Weighted_point Weighted_point; + +/// @} + +/// \name Creation +/// @{ + +/*! +Instantiates a regular triangulation with one vertex (the vertex +at infinity). See the description of the inherited nested type +`Triangulation::Maximal_dimension` for an explanation of +the use of the parameter `dim`. The complex stores a copy of the geometric +traits `gt`. +*/ +Regular_triangulation(const int dim, const Geom_traits gt = Geom_traits()); + +/// @} + +/// \name Point insertion +/// @{ + +/*! +Inserts weighted point `p` in the triangulation and returns the corresponding +vertex. Returns a handle to the (possibly newly created) vertex at that +position. +Prior to the actual insertion, `p` is located in the triangulation; +`hint` is used as a starting place for locating `p`. +*/ +Vertex_handle insert(const Weighted_point & p, Full_cell_handle hint + = Full_cell_handle()); + +/*! +Same as above but uses a vertex as starting place for the search. +*/ +Vertex_handle insert(const Weighted_point & p, Vertex_handle hint); + +/*! +\cgalAdvancedBegin +Inserts weighted point `p` in the triangulation and returns the corresponding +vertex. Similar to the above `insert()` function, but takes as additional +parameter the return values of a previous location query. See description of +`Triangulation::locate()`. +\cgalAdvancedEnd +*/ +Vertex_handle insert(const Weighted_point & p, const Locate_type lt, + const Face & f, const Facet & ft, const Full_cell_handle c); + +/*! +Inserts the weighted points found in range `[s,e)` in the regular triangulation. +Returns the difference of the number of vertices between after and +before the insertions (it may be negative due to hidden points). +Note that this function is not guaranteed to insert the points +following the order of `InputIterator`, as `spatial_sort()` +is used to improve efficiency. + +\tparam ForwardIterator must be an input iterator with the value +type `Weighted_point`. +*/ +template< typename ForwardIterator > +std::ptrdiff_t insert(ForwardIterator s, ForwardIterator e); + +/*! +\cgalAdvancedBegin +Inserts the point `p` in the regular triangulation. Returns a handle to the +(possibly newly created) vertex at that position. +\pre The point `p` +must lie outside the affine hull of the regular triangulation. This implies that +`rt`.`current_dimension()` must be less than `rt`.`maximal_dimension()`. +\cgalAdvancedEnd +*/ +Vertex_handle insert_outside_affine_hull(const Weighted_point & p); + +/*! +\cgalAdvancedBegin +Inserts the point `p` in the regular triangulation. Returns a handle to the +(possibly newly created) vertex at that position. +\pre The point `p` must be in conflict with the full cell `c`. +\cgalAdvancedEnd +*/ +Vertex_handle insert_in_conflicting_cell(const Weighted_point & p, const +Full_cell_handle c); + +/// @} + +/// \name Queries +/// @{ + +/*! +Returns `true` if and only if the point `p` is in +conflict with full cell `c` (A weighted point `p` is said to be in conflict +with a cell `c` if it has a negative power distance to the power sphere of `c`.) +*/ +bool is_in_conflict(const Weighted_point & p, Full_cell_const_handle c) +const; + +/*! +\cgalAdvancedBegin +Outputs handles to the full cells in conflict with +point `p` into the `OutputIterator out`. The full cell `c` is used +as a starting point for gathering the full cells in conflict with +`p`. +A facet `(cc,i)` on the boundary of the conflict zone with +`cc` in conflict is returned. +\pre `c` is in conflict with `p` and `rt`.`current_dimension()`\f$ \geq2\f$. +\cgalAdvancedEnd +*/ +template< typename OutputIterator > +Facet compute_conflict_zone(const Weighted_point & p, const Full_cell_handle c, +OutputIterator out) const; + +/// @} + +}; /* end regular_triangulation */ +} /* end namespace CGAL */ From 950978b2cf81755e50cd1efe3f9e187c441b12fc Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 3 Sep 2015 18:20:52 +0200 Subject: [PATCH 338/487] Clean-up Regular_triangulation_euclidean_traits --- .../CGAL/Regular_triangulation_euclidean_traits.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 3f5a9630a85..b896b3978e8 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -36,16 +36,12 @@ class Regular_triangulation_euclidean_traits { public: typedef K Base; - typedef Regular_triangulation_euclidean_traits Self; // Types from K - - typedef K Kernel; typedef typename K::Dimension Dimension; typedef typename K::FT FT; typedef typename K::Point_d Bare_point; typedef typename K::Weighted_point_d Weighted_point; - typedef Weighted_point Weighted_point_d; typedef Weighted_point Point_d; typedef typename K::Construct_weighted_point_d Construct_weighted_point_d; @@ -53,6 +49,7 @@ public: typedef typename K::In_flat_power_test_d In_flat_power_test_d; typedef typename K::Flat_orientation_d Flat_orientation_d; typedef typename K::Point_drop_weight_d Point_drop_weight_d; + typedef typename K::Point_weight_d Point_weight_d; //============================================================================= // Custom types @@ -142,7 +139,7 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end, - const Weighted_point_d & p) const + const Weighted_point & p) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.contained_in_affine_hull_d_object() ( @@ -166,7 +163,7 @@ public: : m_kernel(kernel) {} result_type operator()( - const Weighted_point_d & p, const Weighted_point_d & q) const + const Weighted_point & p, const Weighted_point & q) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.compare_lexicographically_d_object()(pdw(p), pdw(q)); @@ -186,7 +183,7 @@ public: : m_kernel(kernel) {} result_type operator()( - const Weighted_point_d & p, const int i) const + const Weighted_point & p, const int i) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); m_kernel.compute_coordinate_d_object()(pdw(p), i); @@ -207,7 +204,7 @@ public: : m_kernel(kernel) {} result_type operator()( - const Weighted_point_d & p) const + const Weighted_point & p) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.point_dimension_d_object()(pdw(p)); From eae505f4f121f2c1f5d38131936c514da00d9c95 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 3 Sep 2015 18:21:53 +0200 Subject: [PATCH 339/487] Example for Regular_triangulation --- Triangulation/doc/Triangulation/examples.txt | 1 + .../examples/Triangulation/CMakeLists.txt | 1 + .../Triangulation/regular_triangulation.cpp | 43 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 Triangulation/examples/Triangulation/regular_triangulation.cpp diff --git a/Triangulation/doc/Triangulation/examples.txt b/Triangulation/doc/Triangulation/examples.txt index 7837f9302d2..36db1597b8f 100644 --- a/Triangulation/doc/Triangulation/examples.txt +++ b/Triangulation/doc/Triangulation/examples.txt @@ -1,6 +1,7 @@ /*! \example barycentric_subdivision.cpp \example delaunay_triangulation.cpp +\example regular_triangulation.cpp \example triangulation.cpp \example triangulation1.cpp \example triangulation2.cpp diff --git a/Triangulation/examples/Triangulation/CMakeLists.txt b/Triangulation/examples/Triangulation/CMakeLists.txt index a11f3ea2687..f370b6c863c 100644 --- a/Triangulation/examples/Triangulation/CMakeLists.txt +++ b/Triangulation/examples/Triangulation/CMakeLists.txt @@ -22,6 +22,7 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "barycentric_subdivision.cpp" ) create_single_source_cgal_program( "delaunay_triangulation.cpp" ) + create_single_source_cgal_program( "regular_triangulation.cpp" ) create_single_source_cgal_program( "triangulation.cpp" ) create_single_source_cgal_program( "triangulation_data_structure_dynamic.cpp" ) create_single_source_cgal_program( "triangulation_data_structure_static.cpp" ) diff --git a/Triangulation/examples/Triangulation/regular_triangulation.cpp b/Triangulation/examples/Triangulation/regular_triangulation.cpp new file mode 100644 index 00000000000..941a5e5ba19 --- /dev/null +++ b/Triangulation/examples/Triangulation/regular_triangulation.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +const int D = 5; // Dimension +const int N = 100; // Number of points +typedef CGAL::Epick_d< CGAL::Dimension_tag > K; +typedef CGAL::Regular_triangulation_euclidean_traits Traits; +typedef Traits::Bare_point Bare_point; +typedef Traits::Weighted_point Weighted_point; +typedef CGAL::Regular_triangulation T; + +int main() +{ + // Instanciate a random point generator + CGAL::Random rng(0); + typedef CGAL::Random_points_in_cube_d Random_points_iterator; + Random_points_iterator rand_it(D, 1.0, rng); + + // Generate N random points + std::vector points; + for (int i = 0; i < N; ++i) + points.push_back(Weighted_point(*rand_it++, rng.get_double(0., 10.))); + + T t(D); + CGAL_assertion(t.empty()); + + // Insert the points in the triangulation + t.insert(points.begin(), points.end()); + CGAL_assertion( t.is_valid() ); + std::cout << "Regular triangulation successfully computed: " + << t.number_of_vertices() << " vertices, " + << t.number_of_finite_full_cells() << " finite cells." + << std::endl; + + return 0; +} From 8342b928354e211a6883abffb9d3b5a414b3391d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 3 Sep 2015 18:22:20 +0200 Subject: [PATCH 340/487] Add regular triangulations to the user manual --- .../doc/Triangulation/Triangulation.txt | 72 +++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 2bea12d55e7..88d92e690ca 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -12,9 +12,9 @@ This package proposes data structures and algorithms to compute triangulations of points in any dimensions. The `Triangulation_data_structure` handles the combinatorial aspect of triangulations while the geometric classes -`Triangulation` and `Delaunay_triangulation` allows to -compute and maintain triangulations and Delaunay triangulations of -sets of points. +`Triangulation`, `Delaunay_triangulation` and `Regular_triangulation` allow to +compute and maintain triangulations, Delaunay triangulations and +regular triangulations of sets of points. # Introduction # @@ -81,6 +81,12 @@ In a Delaunay triangulation, each face has the so-called circumscribing ball whose interior does not contain any vertex of the triangulation. +The class `CGAL::Regular_triangulation` +builds the regular triangulation +-- also known as weighted Delaunay triangulation -- of a set of points. +A detailed description of such a triangulation is available in section +\ref TriangulationSecRT. + ## Further Definitions ## An \f$ i\f$-face denotes an \f$ i\f$-dimensional simplex, or a simplex with \f$ i+1\f$ @@ -387,7 +393,7 @@ visits only the infinite full cells but stores handles to them into the The class `CGAL::Delaunay_triangulation` derives from `CGAL::Triangulation` -and represent Delaunay triangulations. +and represents Delaunay triangulations. A circumscribing ball of a simplex is a ball having all vertices of the simplex on its boundary. @@ -439,6 +445,61 @@ retaining an efficient update of the Delaunay triangulation. \cgalExample{delaunay_triangulation.cpp} +\section TriangulationSecRT Regular Triangulations + +The class `CGAL::Regular_triangulation` derives from +`CGAL::Triangulation` +and represents regular triangulations. + +A regular triangulation is similar to Delaunay triangulations, but +with weighted points. + +Let \f$ {S}^{(w)}\f$ be a set of weighted points in \f$ \mathbb{R}^D\f$. Let +\f$ {p}^{(w)}=(p,w_p), p\in\mathbb{R}^D, w_p\in\mathbb{R}\f$ and +\f$ {z}^{(w)}=(z,w_z), z\in\mathbb{R}^D, w_z\in\mathbb{R}\f$ +be two weighted points. +A weighted point +\f$ {p}^{(w)}=(p,w_p)\f$ can also be seen as a sphere of center \f$ p\f$ and +radius \f$ \sqrt{w_p}\f$. +The power product (or power distance ) +between \f$ {p}^{(w)}\f$ and \f$ {z}^{(w)}\f$ is +defined as +\f[ \Pi({p}^{(w)},{z}^{(w)}) = {\|{p-z}\|^2-w_p-w_z} \f] +where \f$ \|{p-z}\|\f$ is the Euclidean distance between \f$ p\f$ and \f$ z\f$. +\f$ {p}^{(w)}\f$ and \f$ {z}^{(w)}\f$ +are said to be orthogonal if \f$ \Pi{({p}^{(w)}-{z}^{(w)})} += 0\f$. + +\f$D + 1\f$ weighted points have a unique common orthogonal weighted point +called the power sphere. A sphere \f$ {z}^{(w)}\f$ is said to be +regular if \f$ \forall {p}^{(w)}\in{S}^{(w)}, +\Pi{({p}^{(w)}-{z}^{(w)})}\geq 0\f$. + +A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres +of all simplices are regular. + +Note that the removal of points is not supported yet. + +## Implementation ## + +The class `CGAL::Regular_triangulation` derives from +`CGAL::Triangulation`. It thus stores a model of +the concept `TriangulationDataStructure` which is instantiated with a vertex +type that stores a weighted point and allows its retrieval. + +The template parameter `RegularTriangulationTraits` must be a model of the concept +`RegularTriangulationTraits` which provides the `Bare_point`and `Weighted_point` +types as well as various geometric predicates used by the +`Regular_triangulation` class. +The concept `RegularTriangulationTraits` refines the concept +`TriangulationTraits`. + +## Example ## + +This simple example shows how to create a regular triangulation. + +\cgalExample{regular_triangulation.cpp} + # Complexity and Performances # The current implementation locates points by walking in the @@ -477,7 +538,8 @@ This package is heavily inspired by the works of Monique Teillaud and Sylvain Pion (`Triangulation_3`) and Mariette Yvinec (`Triangulation_2`). The first version was written by Samuel Hornus. The final version is a joint -work by Samuel Hornus, Olivier Devillers and Clément Jamin. +work by Samuel Hornus, Olivier Devillers and Clément Jamin. In 2015, Clément +Jamin added the regular triangulations. Starting with the version 2.3 of \cgal, a package written by Susan Hert and Michael Seel was the first able to deal with triangulation and convex hulls in arbitrary From cd9aeb3c3ba55e74f8a7a47d5e292454a367aeac Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 4 Sep 2015 08:42:28 +0200 Subject: [PATCH 341/487] Remove unused includes --- .../include/CGAL/Regular_triangulation_euclidean_traits.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index b896b3978e8..1af8a92157a 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -21,10 +21,6 @@ #define CGAL_REGULAR_TRIANGULATION_EUCLIDEAN_TRAITS_H #include -#include -#include -#include -#include #include @@ -35,7 +31,7 @@ class Regular_triangulation_euclidean_traits : public K { public: - typedef K Base; + typedef K Base; // Types from K typedef typename K::Dimension Dimension; From 76297ebca39b02f0a058df2a68cb6a2e43a5f4ef Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 4 Sep 2015 08:55:54 +0200 Subject: [PATCH 342/487] Clean-up Regular_triangulation_euclidean_traits (unused types, etc.) --- .../include/CGAL/Regular_triangulation.h | 2 - .../Regular_triangulation_euclidean_traits.h | 41 +++++++++++-------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index fda64bb9d8d..59f74890a01 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -52,12 +52,10 @@ class Regular_triangulation typedef Regular_triangulation Self; typedef typename RTTraits::Orientation_d Orientation_d; - typedef typename RTTraits::Construct_weighted_point_d Construct_weighted_point_d; typedef typename RTTraits::Power_test_d Power_test_d; typedef typename RTTraits::In_flat_power_test_d In_flat_power_test_d; typedef typename RTTraits::Flat_orientation_d Flat_orientation_d; typedef typename RTTraits::Construct_flat_orientation_d Construct_flat_orientation_d; - typedef typename RTTraits::In_flat_orientation_d In_flat_orientation_d; public: // PUBLIC NESTED TYPES diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 1af8a92157a..eb3009a0421 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -33,24 +33,25 @@ class Regular_triangulation_euclidean_traits public: typedef K Base; - // Types from K + // Required by TriangulationTraits typedef typename K::Dimension Dimension; typedef typename K::FT FT; + typedef typename K::Flat_orientation_d Flat_orientation_d; + typedef typename K::Weighted_point_d Point_d; + + // Required by RegularTriangulationTraits typedef typename K::Point_d Bare_point; typedef typename K::Weighted_point_d Weighted_point; - typedef Weighted_point Point_d; - - typedef typename K::Construct_weighted_point_d Construct_weighted_point_d; typedef typename K::Power_test_d Power_test_d; typedef typename K::In_flat_power_test_d In_flat_power_test_d; - typedef typename K::Flat_orientation_d Flat_orientation_d; typedef typename K::Point_drop_weight_d Point_drop_weight_d; typedef typename K::Point_weight_d Point_weight_d; - - //============================================================================= + + //=========================================================================== // Custom types - //============================================================================= + //=========================================================================== + // Required by TriangulationTraits class Orientation_d { const K &m_kernel; @@ -72,8 +73,9 @@ public: } }; - //============================================================================= + //=========================================================================== + // Required by TriangulationTraits class Construct_flat_orientation_d { const K &m_kernel; @@ -96,8 +98,9 @@ public: }; - //============================================================================= + //=========================================================================== + // Required by TriangulationTraits class In_flat_orientation_d { const K &m_kernel; @@ -121,8 +124,9 @@ public: } }; - //============================================================================= - + //=========================================================================== + + // Required by TriangulationTraits class Contained_in_affine_hull_d { const K &m_kernel; @@ -146,8 +150,9 @@ public: } }; - //============================================================================= + //=========================================================================== + // Required by TriangulationTraits class Compare_lexicographically_d { const K &m_kernel; @@ -166,8 +171,9 @@ public: } }; - //============================================================================= + //=========================================================================== + // Only for Triangulation_off_ostream.h (undocumented) class Compute_coordinate_d { const K &m_kernel; @@ -187,8 +193,9 @@ public: } }; - //============================================================================= + //=========================================================================== + // Only for Triangulation_off_ostream.h (undocumented) class Point_dimension_d { const K &m_kernel; @@ -207,9 +214,9 @@ public: } }; - //============================================================================= + //=========================================================================== // Object creation - //============================================================================= + //=========================================================================== Contained_in_affine_hull_d contained_in_affine_hull_d_object() const { From 0d2ea9f2f3fc65f1699511510fed5810882e6a51 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 4 Sep 2015 13:15:14 +0200 Subject: [PATCH 343/487] Move code around --- .../include/CGAL/Regular_triangulation_euclidean_traits.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index eb3009a0421..c5643ae2d06 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -42,10 +42,10 @@ public: // Required by RegularTriangulationTraits typedef typename K::Point_d Bare_point; typedef typename K::Weighted_point_d Weighted_point; - typedef typename K::Power_test_d Power_test_d; - typedef typename K::In_flat_power_test_d In_flat_power_test_d; typedef typename K::Point_drop_weight_d Point_drop_weight_d; typedef typename K::Point_weight_d Point_weight_d; + typedef typename K::Power_test_d Power_test_d; + typedef typename K::In_flat_power_test_d In_flat_power_test_d; //=========================================================================== // Custom types From 6c0c75fb333a80887d075875a6f4d098cbfd9b59 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 4 Sep 2015 13:15:48 +0200 Subject: [PATCH 344/487] RegularTriangulationTraits concept documentation --- .../Concepts/RegularTriangulationTraits.h | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h new file mode 100644 index 00000000000..c1d7799e47c --- /dev/null +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -0,0 +1,136 @@ + +/*! +\ingroup PkgTriangulationsConcepts +\cgalConcept + +This concept describes the geometric types and predicates required to build +a regular triangulation. It corresponds to the first template parameter of the class +`CGAL::Regular_triangulation`. + +\cgalRefines ::TriangulationTraits. + +\cgalHasModel `CGAL::Epick_d` + +\sa `TriangulationTraits` +*/ +class RegularTriangulationTraits { +public: + +/// \name Types +/// @{ + +/*! +An arithmetic field type. +*/ +typedef unspecified_type FT; + +/*! +The weighted point type. +*/ +typedef unspecified_type Weighted_point; + +/*! +The un-weighted point type. +*/ +typedef unspecified_type Bare_point; + +/*! +A predicate object that must provide the templated operator +`template Bare_point operator()(const Weighted_point & wp)`, returning +`wp` without its weight. +*/ +typedef unspecified_type Point_drop_weight_d; + +/*! +A predicate object that must provide the templated operator +`template FT operator()(const Weighted_point & wp)`, returning +the weight of `wp`. +*/ +typedef unspecified_type Point_weight_d; + +/*! +A predicate object that must provide the templated operator +`template Oriented_side operator()(ForwardIterator start, ForwardIterator end, const Point_d & p)`. +Let \f$ S \f$ be the power sphere of the weighted points in range `[start,end)`. +The operator returns: +- `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to + \f$ S \f$, + +- `ON_NEGATIVE_SIDE` if `p` lies outside the oriented sphere of + the same center as \f$ S \f$ and radius \f$ \sqrt{ w_S^2 + w_p^2 }\f$, + +- `ON_POSITIVE_SIDE` if `p` lies inside this oriented sphere. + +\pre If `Dimension`=`CGAL::``Dimension_tag`, +then `std::distance(start,end)=D+1`. +The points in range +`[start,end)` must be affinely independent, i.e., the simplex must +not be flat. +*/ +typedef unspecified_type Power_test_d; + +/*! +A predicate object that must provide the templated operator +`template Oriented_side operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end, const Point_d & p)`. + +The points in range `[start,end)` and `p` are supposed to belong to the lower dimensional flat +whose orientation is given by `orient`. + +Let \f$ S \f$ be the power sphere of the weighted points in range `[start,end)` +in this lower dimensional flat. +The operator returns: +- `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to +\f$ S \f$, + +- `ON_NEGATIVE_SIDE` if `p` lies outside the oriented sphere of +the same center as \f$ S \f$ and radius \f$ \sqrt{ w_S^2 + w_p^2 }\f$, + +- `ON_POSITIVE_SIDE` if `p` lies inside this oriented sphere. + +\pre `std::distance(start,end)=k+1` where \f$ k\f$ is the number of +points used to construct `orient`. +The points in range +`[start,end)` must be affinely independent, i.e., the simplex must +not be flat. `p` must be in the flat generated by this simplex. +*/ +typedef unspecified_type In_flat_power_test_d; + +/// @} + +/// \name Creation +/// @{ + +/*! +The default constructor. +*/ +RegularTriangulationTraits(); + +/// @} + +/// \name Operations +/// The following methods permit access to the traits class's predicates: +/// @{ + +/*! + +*/ +Point_drop_weight_d point_drop_weight_d_object() const; + +/*! + +*/ +Point_weight_d point_weight_d_object() const; + +/*! + +*/ +Power_test_d power_test_d_object() const; + +/*! + +*/ +In_flat_power_test_d in_flat_power_test_d_object() const; + +/// @} + +}; /* end RegularTriangulationTraits */ From 816b036564906e1f3e3f26021cdb979983208d54 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 7 Sep 2015 17:10:14 +0200 Subject: [PATCH 345/487] Missing typedef --- Triangulation/include/CGAL/Delaunay_triangulation.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 30fe8d6c1b5..5fdfbf2b3ff 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -75,6 +75,8 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Full_cell_iterator Full_cell_iterator; typedef typename Base::Full_cell_const_handle Full_cell_const_handle; typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename Base::Finite_full_cell_const_iterator + Finite_full_cell_const_iterator; typedef typename Base::size_type size_type; typedef typename Base::difference_type difference_type; From b6793e6c7a8f98c6e552c93f45f3dccdd90c1c33 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 7 Sep 2015 17:12:54 +0200 Subject: [PATCH 346/487] Missing using --- Triangulation/include/CGAL/Delaunay_triangulation.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 5fdfbf2b3ff..56b2998f54c 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -117,6 +117,8 @@ public: using Base::full_cell; using Base::full_cells_begin; using Base::full_cells_end; + using Base::finite_full_cells_begin; + using Base::finite_full_cells_end; using Base::vertices_begin; using Base::vertices_end; // using Base:: From 278c0c93e86a36e54295d771fffed939ccb5593d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 7 Sep 2015 17:16:06 +0200 Subject: [PATCH 347/487] Missing using --- Triangulation/include/CGAL/Delaunay_triangulation.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 56b2998f54c..dbbbe0b8c5a 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -103,6 +103,7 @@ public: using Base::index_of_covertex; //using Base::index_of_second_covertex; using Base::infinite_vertex; + using Base::rotate_rotor; using Base::insert_in_hole; using Base::insert_outside_convex_hull_1; using Base::is_infinite; From 0083ea06bc014863828886add6d95f90696495f2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 7 Sep 2015 17:38:33 +0200 Subject: [PATCH 348/487] Missing typedef and typename --- Triangulation/include/CGAL/IO/Triangulation_off_ostream.h | 2 +- Triangulation/include/CGAL/Regular_triangulation.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 2e09b9431e2..0f12fdfcc6c 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -166,7 +166,7 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) while (line_sstr >> temp) coords.push_back(temp); - std::vector::iterator last = coords.end() - 1; + typename std::vector::iterator last = coords.end() - 1; P p = P(coords.begin(), last); wp = WP(p, *last); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 59f74890a01..7eb73c545e6 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -226,11 +226,11 @@ public: typedef boost::function_property_map< typename Geom_traits::Point_drop_weight_d, - Point, + Weighted_point, Bare_point> Drop_weight_pmap; typedef CGAL::Spatial_sort_traits_adapter_d< typename Geom_traits::Base, Drop_weight_pmap> Search_traits_d; - Search_traits_d st_d(boost::make_function_property_map( + Search_traits_d st_d(boost::make_function_property_map( geom_traits().point_drop_weight_d_object())); spatial_sort(points.begin(), points.end(), st_d); From 225d93dfcae704fa20d788c9ea97f7fa40d80516 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 9 Sep 2015 17:03:21 +0200 Subject: [PATCH 349/487] Add regular triangulation --- Triangulation/doc/Triangulation/PackageDescription.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 74bf579a9e2..3e0481e7f22 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -84,6 +84,7 @@ is opposite to the vertex with the same index. - `TriangulationTraits` - `DelaunayTriangulationTraits` +- `RegularTriangulationTraits` - `TriangulationVertex` - `TriangulationFullCell` @@ -102,6 +103,7 @@ The latter two concepts are also abbreviated respectively as `TrVertex` and `TrF - `CGAL::Triangulation` - `CGAL::Delaunay_triangulation` +- `CGAL::Regular_triangulation` - `CGAL::Triangulation_vertex` - `CGAL::Triangulation_full_cell` From d1f7de10aeb794db88570c1d9a837de7954b121a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 14 Sep 2015 11:13:48 +0200 Subject: [PATCH 350/487] Weighted_point_d must be the same as Point_d --- .../doc/Triangulation/Concepts/RegularTriangulationTraits.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index c1d7799e47c..46a700570c7 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -25,7 +25,7 @@ An arithmetic field type. typedef unspecified_type FT; /*! -The weighted point type. +The weighted point type. Must be the same type as `TriangulationTraits::Point_d`. */ typedef unspecified_type Weighted_point; From 9778973252a1a89620152b0c6ab8051197cfca62 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 14 Sep 2015 11:18:14 +0200 Subject: [PATCH 351/487] Too much templates will kill you --- .../Triangulation/Concepts/RegularTriangulationTraits.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 46a700570c7..d7e503daa24 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -35,15 +35,15 @@ The un-weighted point type. typedef unspecified_type Bare_point; /*! -A predicate object that must provide the templated operator -`template Bare_point operator()(const Weighted_point & wp)`, returning +A predicate object that must provide the operator +`Bare_point operator()(const Weighted_point & wp)`, returning `wp` without its weight. */ typedef unspecified_type Point_drop_weight_d; /*! -A predicate object that must provide the templated operator -`template FT operator()(const Weighted_point & wp)`, returning +A predicate object that must provide the operator +`FT operator()(const Weighted_point & wp)`, returning the weight of `wp`. */ typedef unspecified_type Point_weight_d; From e2bd4e9fee905800ae781af8b50a34c45777a019 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 16 Sep 2015 14:06:28 +0200 Subject: [PATCH 352/487] Make the default constructor optional --- .../doc/Triangulation/Concepts/DelaunayTriangulationTraits.h | 4 +++- .../doc/Triangulation/Concepts/RegularTriangulationTraits.h | 4 +++- .../doc/Triangulation/Concepts/TriangulationTraits.h | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h index c7773eba7bf..ff0e09edfb5 100644 --- a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h @@ -70,7 +70,9 @@ typedef unspecified_type In_flat_side_of_oriented_sphere_d; /// @{ /*! -The default constructor. +The default constructor (optional). +This is not required if an instance of the traits will be provided +to the constructor of `CGAL::Delaunay_triangulation`. */ DelaunayTriangulationTraits(); diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index d7e503daa24..b349115197d 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -101,7 +101,9 @@ typedef unspecified_type In_flat_power_test_d; /// @{ /*! -The default constructor. +The default constructor (optional). +This is not required if an instance of the traits will be provided +to the constructor of `CGAL::Regular_triangulation`. */ RegularTriangulationTraits(); diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h index d66dd83d7f1..36e2b8a5d33 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h @@ -137,7 +137,9 @@ typedef unspecified_type Compare_lexicographically_d; /// @{ /*! -The default constructor. +The default constructor (optional). +This is not required if an instance of the traits will be provided +to the constructor of `CGAL::Triangulation`. */ TriangulationTraits(); From 2130a21fd27a846a4dc603c0171dd3cb29a5cb63 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 23 Sep 2015 18:10:20 +0200 Subject: [PATCH 353/487] Use \warning to emphasize the fact that removal is not supported --- Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h | 2 +- Triangulation/doc/Triangulation/Triangulation.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 3602dae1773..8e530137e38 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -11,7 +11,7 @@ The dimension \f$ D\f$ can be specified at compile-time or run-time. It should be kept reasonably small -- see the performance section in the user manual for what reasonable means. -Note that the removal of points is not supported yet. +\warning The removal of points is not supported yet. A regular triangulation is defined as follows. diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 88d92e690ca..286d3b3cbdb 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -478,7 +478,7 @@ called the power sphere. A sphere \f$ {z}^{(w)}\f$ is said to be A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres of all simplices are regular. -Note that the removal of points is not supported yet. +\warning The removal of points is not supported yet. ## Implementation ## @@ -488,7 +488,7 @@ the concept `TriangulationDataStructure` which is instantiated with a vertex type that stores a weighted point and allows its retrieval. The template parameter `RegularTriangulationTraits` must be a model of the concept -`RegularTriangulationTraits` which provides the `Bare_point`and `Weighted_point` +`RegularTriangulationTraits` which provides the `Bare_point`and `%Weighted_point` types as well as various geometric predicates used by the `Regular_triangulation` class. The concept `RegularTriangulationTraits` refines the concept From 1627349593cd1a1f1c86cbe0d822d605cdf49d37 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 23 Sep 2015 18:12:42 +0200 Subject: [PATCH 354/487] Remove a sentence that was wrong --- Triangulation/doc/Triangulation/Triangulation.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 286d3b3cbdb..a2e6afa7c79 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -504,10 +504,7 @@ This simple example shows how to create a regular triangulation. The current implementation locates points by walking in the triangulation, and sorts the points with spatial sort to insert a -set of points. Thus the theoretical complexity are -\f$ O(n\log n)\f$ for inserting \f$ n\f$ random points and \f$ O(n^{\frac{1}{d}})\f$ -for inserting one point in a triangulation of \f$ n\f$ random points. -In the worst case, the expected complexity is +set of points. In the worst case, the expected complexity is \f$ O(n^{\lceil\frac{d}{2}\rceil}+n\log n)\f$. We provide below (Figure \cgalFigureRef{Triangulationfigbenchmarks}) the From 0cfa5d0a7178e62f02e117abe6823936a563f27a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 24 Sep 2015 10:20:40 +0200 Subject: [PATCH 355/487] Use alphabetical order for authors --- Triangulation/doc/Triangulation/PackageDescription.txt | 2 +- Triangulation/doc/Triangulation/Triangulation.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 3e0481e7f22..82e743c13d5 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -13,7 +13,7 @@ \cgalPkgDescriptionBegin{dD Triangulations,PkgTriangulationsSummary} \cgalPkgPicture{detail.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Samuel Hornus, Olivier Devillers and Clément Jamin} +\cgalPkgAuthors{Olivier Devillers, Samuel Hornus, and Clément Jamin} \cgalPkgDesc{This package provides classes for manipulating triangulations (pure simplicial complexes) in Euclidean spaces whose dimension can be specified at compile-time or at run-time. Specifically, it provides a diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index a2e6afa7c79..48a213b413e 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -6,7 +6,7 @@ namespace CGAL { \anchor Chapter_Triangulations \cgalAutoToc -\authors Samuel Hornus, Olivier Devillers and Clément Jamin. +\authors Olivier Devillers, Samuel Hornus, and Clément Jamin. This package proposes data structures and algorithms to compute triangulations of points in any dimensions. From 9b879d294e2021f58b1dc1af6eb3e477aaf3d970 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 9 Oct 2015 15:35:17 +0200 Subject: [PATCH 356/487] Fix doc according to Jean-Daniel's review --- .../doc/Triangulation/Triangulation.txt | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 48a213b413e..4964b4c111b 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -283,8 +283,7 @@ full cells adjacent to `c` are automatically subdivided to match the subdivision of the full cell `c`. The barycentric subdivision of `c` is obtained by enumerating all the faces of `c` in order of decreasing dimension, from the dimension of `c` to dimension 1, and inserting a new -vertex in each face. For the enumeration, we use a combination enumerator, -which is not documented, but provided in \cgal. +vertex in each face. \cgalFigureBegin{triangulationfigbarycentric,barycentric-subdivision.png} Barycentric subdivision in dimension \f$ d=2\f$. @@ -416,7 +415,10 @@ in the conflict zone are removed, leaving a hole that contains `p`. That hole is ``star shaped'' around `p` and thus is re-triangulated using `p` as a center vertex. -Delaunay triangulations also support vertex removal. +Delaunay triangulations support insertion of points, removal of vertices, +and localization of a query point inside the triangulation. +Note that inserting a set of points at once is much faster +than inserting the points one by one. ## Implementation ## @@ -451,7 +453,7 @@ The class `CGAL::Regular_triangulation` and represents regular triangulations. -A regular triangulation is similar to Delaunay triangulations, but +Regular triangulations are similar to Delaunay triangulations, but with weighted points. Let \f$ {S}^{(w)}\f$ be a set of weighted points in \f$ \mathbb{R}^D\f$. Let @@ -478,7 +480,12 @@ called the power sphere. A sphere \f$ {z}^{(w)}\f$ is said to be A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres of all simplices are regular. -\warning The removal of points is not supported yet. +Regular triangulations support insertion of points, +and localization of a query point inside the triangulation. +Note that inserting a set of points at once is much faster +than inserting the points one by one. +\warning The removal of vertices is not supported yet. + ## Implementation ## @@ -505,7 +512,9 @@ This simple example shows how to create a regular triangulation. The current implementation locates points by walking in the triangulation, and sorts the points with spatial sort to insert a set of points. In the worst case, the expected complexity is -\f$ O(n^{\lceil\frac{d}{2}\rceil}+n\log n)\f$. +\f$ O(n^{\lceil\frac{d}{2}\rceil}+n\log n)\f$. When the algorithm is +run on \f$ n \f$ random points, the cost of inserting one point is +\f$ O(n^{1/d}) \f$. We provide below (Figure \cgalFigureRef{Triangulationfigbenchmarks}) the performance of the Delaunay triangulation on randomly distributed points. From b0328a71920128f86a8675ce02440fd2c138c30e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 9 Oct 2015 15:35:45 +0200 Subject: [PATCH 357/487] Use the documented Combination_enumerator instead of the internal one --- .../examples/Triangulation/barycentric_subdivision.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation/examples/Triangulation/barycentric_subdivision.cpp b/Triangulation/examples/Triangulation/barycentric_subdivision.cpp index 13fba765d3c..08a5ae80ba0 100644 --- a/Triangulation/examples/Triangulation/barycentric_subdivision.cpp +++ b/Triangulation/examples/Triangulation/barycentric_subdivision.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include @@ -34,8 +34,8 @@ void barycentric_subdivide(TDS & tds, typename TDS::Full_cell_handle fc) face_vertices.resize(d+1); // The following class // enumerates all (d+1)-tuple of the set {0, 1, ..., dim} - CGAL::internal::Combination_enumerator combi(d+1, 0, dim); - while( ! combi.end() ) + CGAL::Combination_enumerator combi(d+1, 0, dim); + while ( !combi.finished() ) { for( int i = 0; i <= d; ++i ) face_vertices[i] = vertices[combi[i]]; From 129a4d3ffd537132f057d74b91598019006177a2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 13 Oct 2015 16:09:07 +0200 Subject: [PATCH 358/487] Update performance tables with more details (memory, etc.) --- .../doc/Triangulation/Triangulation.txt | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 4964b4c111b..a9218c13680 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -516,26 +516,45 @@ set of points. In the worst case, the expected complexity is run on \f$ n \f$ random points, the cost of inserting one point is \f$ O(n^{1/d}) \f$. -We provide below (Figure \cgalFigureRef{Triangulationfigbenchmarks}) the +We provide below (Figure \cgalFigureRef{Triangulationfigbenchmarks100} +and \cgalFigureRef{Triangulationfigbenchmarks1000}) the performance of the Delaunay triangulation on randomly distributed points. The machine used is a PC running Windows 7 64-bits with an Intel Xeon CPU clocked at 2.80 GHz with 32GB of RAM. -The program has been compiled with Microsoft Visual C++ 2012 in Release mode. - -\cgalFigureAnchor{Triangulationfigbenchmarks} +The program has been compiled with Microsoft Visual C++ 2013 in Release mode. +\cgalFigureAnchor{Triangulationfigbenchmarks100}
    - +
    + + + + + + + +

    Dimension23456789101112

    Time (s)0.0030.0070.030.140.562.711.3451856862390
    Memory (MB)< 1< 1< 113135318266221877156
    Number of maximal simplices1844871,5485,54819,59867,102230,375715,9842,570,6237,293,29321,235,615
    Number of convex hull facets14663081,1644,41016,97457,589238,406670,5452,574,3268,603,589
    +

    +
    +\cgalFigureCaptionBegin{Triangulationfigbenchmarks100} +Performance of the insertion of 100 points in a Delaunay triangulation. +\cgalFigureCaptionEnd + +\cgalFigureAnchor{Triangulationfigbenchmarks1000} +
    + - - + + + +

    Dimension2345678

    Inserting 100 points0.0030.0070.030.140.562.711.3
    Inserting 1000 points0.0150.0560.523.526.21851385
    Time (s)0.010.050.53.4241831365
    Memory (MB)< 1< 12.714814832827
    Number of maximal simplices1,9796,31525,845122,116596,9273,133,31816,403,337
    Number of convex hull facets191389636,18441,135241,5401,406,797

    -\cgalFigureCaptionBegin{Triangulationfigbenchmarks} -Running times in seconds for algorithms on Delaunay triangulations. +\cgalFigureCaptionBegin{Triangulationfigbenchmarks1000} +Performance of the insertion of 1000 points in a Delaunay triangulation. \cgalFigureCaptionEnd # Design and Implementation History # From 8be2301527b0eb9d75c22c5db47394a5d6e0206d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 13 Oct 2015 17:19:33 +0200 Subject: [PATCH 359/487] Improve benchmark: memory, etc. --- .../benchmark/Triangulation/delaunay.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index 7d1a5b379ee..ee1d6e805a2 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -3,6 +3,8 @@ #include #include #include +#include + #include #include #include @@ -24,6 +26,7 @@ void test(const int d, const std::string & type, const int N) typedef CGAL::Random_points_in_cube_d Random_points_iterator; CGAL::Timer cost; // timer + std::size_t mem_before = CGAL::Memory_sizer().virtual_size(); DT dt(d); assert(dt.empty()); @@ -33,12 +36,15 @@ void test(const int d, const std::string & type, const int N) Random_points_iterator rand_it(d, 2.0, rng); CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); cost.reset();cost.start(); - std::cout << " Delaunay triangulation of "<> 10) << " KB.\n"; std::size_t nbfc= dt.number_of_finite_full_cells(); std::size_t nbc= dt.number_of_full_cells(); - std::cout << dt.number_of_vertices() << " vertices, " + std::cout << " " << dt.number_of_vertices() << " vertices, " << nbfc << " finite simplices and " << (nbc-nbfc) << " convex hull Facets." << std::endl; @@ -64,6 +70,13 @@ int main(int argc, char **argv) go<6>(N); go<7>(N); go<8>(N); + if (N <= 100) + { + go<9>(N); + go<10>(N); + go<11>(N); + go<12>(N); + } return 0; } From 78295259db9bf7272f4d865cf0e9423df97a64fa Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 14 Oct 2015 10:46:17 +0200 Subject: [PATCH 360/487] Reorganize code --- .../benchmark/Triangulation/delaunay.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index ee1d6e805a2..c9c87580a91 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -26,19 +26,23 @@ void test(const int d, const std::string & type, const int N) typedef CGAL::Random_points_in_cube_d Random_points_iterator; CGAL::Timer cost; // timer - std::size_t mem_before = CGAL::Memory_sizer().virtual_size(); - - DT dt(d); - assert(dt.empty()); + // Generate points std::vector points; CGAL::Random rng; Random_points_iterator rand_it(d, 2.0, rng); CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); - cost.reset();cost.start(); - std::cout << "Delaunay triangulation of " << N << + + std::size_t mem_before = CGAL::Memory_sizer().virtual_size(); + cost.reset(); + cost.start(); + + std::cout << "Delaunay triangulation of " << N << " points in dim " << d << ":" << std::endl; + + DT dt(d); dt.insert(points.begin(), points.end()); + std::cout << " Done in " << cost.time() << " seconds." << std::endl; std::cout << " Memory consumption: " << ((CGAL::Memory_sizer().virtual_size() - mem_before) >> 10) << " KB.\n"; From fecb90708656448c8c23523b9fa7e03a1a4691c1 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 14 Oct 2015 11:12:08 +0200 Subject: [PATCH 361/487] Loop until memory limit is reached --- .../benchmark/Triangulation/delaunay.cpp | 70 +++++++++++-------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index c9c87580a91..3b851cdbc1e 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -11,10 +11,19 @@ #include #include +//#define USE_DYNAMIC_KERNEL -template -void test(const int d, const std::string & type, const int N) +// Return the number of Bytes used +template +std::size_t compute_triangulation(std::size_t N) { +#ifdef USE_DYNAMIC_KERNEL + typedef CGAL::Epick_d K; +#else + typedef CGAL::Epick_d > K; +#endif + typedef CGAL::Delaunay_triangulation DT; + typedef typename DT::Vertex Vertex; typedef typename DT::Vertex_handle Vertex_handle; typedef typename DT::Full_cell Full_cell; @@ -30,7 +39,7 @@ void test(const int d, const std::string & type, const int N) // Generate points std::vector points; CGAL::Random rng; - Random_points_iterator rand_it(d, 2.0, rng); + Random_points_iterator rand_it(D, 2.0, rng); CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); std::size_t mem_before = CGAL::Memory_sizer().virtual_size(); @@ -38,49 +47,54 @@ void test(const int d, const std::string & type, const int N) cost.start(); std::cout << "Delaunay triangulation of " << N << - " points in dim " << d << ":" << std::endl; + " points in dim " << D << ":" << std::endl; - DT dt(d); + DT dt(D); dt.insert(points.begin(), points.end()); + std::size_t mem = CGAL::Memory_sizer().virtual_size() - mem_before; std::cout << " Done in " << cost.time() << " seconds." << std::endl; - std::cout << " Memory consumption: " << - ((CGAL::Memory_sizer().virtual_size() - mem_before) >> 10) << " KB.\n"; + std::cout << " Memory consumption: " << (mem >> 10) << " KB.\n"; std::size_t nbfc= dt.number_of_finite_full_cells(); std::size_t nbc= dt.number_of_full_cells(); std::cout << " " << dt.number_of_vertices() << " vertices, " << nbfc << " finite simplices and " << (nbc-nbfc) << " convex hull Facets." << std::endl; + + return mem; } -template< int D > -void go(const int N) +// Will compute triangulations of i*num_points_steps points, +// with i in [1, 2...], stopping after the last computation that takes +// more memory than mem_threshold_in_bytes +template +void go( + std::size_t num_points_increment, + std::size_t mem_threshold_in_MB = (3 << 10)) // 3 GB { - typedef CGAL::Epick_d > K; - //typedef CGAL::Epick_d K; - typedef CGAL::Delaunay_triangulation Triangulation; - test(D, "static", N); + std::size_t mem = 0; + for (std::size_t i = 1 ; mem < (mem_threshold_in_MB << 20) ; ++i) + { + mem = compute_triangulation(i*num_points_increment); + } } int main(int argc, char **argv) { srand(static_cast(time(NULL))); - int N = 100; if( argc > 1 ) N = atoi(argv[1]); - go<2>(N); - go<3>(N); - go<4>(N); - go<5>(N); - go<6>(N); - go<7>(N); - go<8>(N); - if (N <= 100) - { - go<9>(N); - go<10>(N); - go<11>(N); - go<12>(N); - } + //int N = 100; if( argc > 1 ) N = atoi(argv[1]); + go<2>(100000); + go<3>(10000); + go<4>(1000); + go<5>(1000); + go<6>(1000); + go<7>(1000); + go<8>(1000); + go<9>(100); + go<10>(100); + go<11>(50); + go<12>(50); return 0; } From 409b2773d408ea93d6ae4edb75338e1be988d5b9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 16 Oct 2015 10:04:48 +0200 Subject: [PATCH 362/487] Move misplaced header inclusion --- Triangulation/include/CGAL/Triangulation.h | 1 + Triangulation/include/CGAL/Triangulation_vertex.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index dc3df8adc0c..3a713defc4b 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/Triangulation/include/CGAL/Triangulation_vertex.h b/Triangulation/include/CGAL/Triangulation_vertex.h index 2a7c75e87e8..f364717f466 100644 --- a/Triangulation/include/CGAL/Triangulation_vertex.h +++ b/Triangulation/include/CGAL/Triangulation_vertex.h @@ -22,7 +22,6 @@ #include #include -#include namespace CGAL { From bbf1f1bed768b62ad01d5a6f60413b4bf4898e47 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 16 Oct 2015 10:16:55 +0200 Subject: [PATCH 363/487] Change steps --- Triangulation/benchmark/Triangulation/delaunay.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index 3b851cdbc1e..dbb65fc3e64 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -84,10 +84,10 @@ int main(int argc, char **argv) { srand(static_cast(time(NULL))); //int N = 100; if( argc > 1 ) N = atoi(argv[1]); - go<2>(100000); - go<3>(10000); - go<4>(1000); - go<5>(1000); + go<2>(1e7); + go<3>(1e6); + go<4>(1e5); + go<5>(1e4); go<6>(1000); go<7>(1000); go<8>(1000); From 019b685b9720636df46719516314263b3f6aa9c3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 16 Oct 2015 11:00:46 +0200 Subject: [PATCH 364/487] Use get_default_random() --- Triangulation/examples/Triangulation/delaunay_triangulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp index 09522340e1c..6f500ab9932 100644 --- a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp +++ b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp @@ -22,7 +22,7 @@ int main(int argc, char **argv) // Instanciate a random point generator typedef CGAL::Random_points_in_cube_d Random_points_iterator; - Random_points_iterator rand_it(D, 1.0, CGAL::default_random); + Random_points_iterator rand_it(D, 1.0, CGAL::get_default_random()); // Generate N random points std::vector points; CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); From 5f1c3dd3f4481f291057cc6b23e2caa7f7d168cd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 16 Oct 2015 12:03:10 +0200 Subject: [PATCH 365/487] Export stats into CSV file --- .../benchmark/Triangulation/delaunay.cpp | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index dbb65fc3e64..1f00e2aee55 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -12,6 +12,11 @@ #include //#define USE_DYNAMIC_KERNEL +#define OUTPUT_STATS_IN_CSV + +#ifdef OUTPUT_STATS_IN_CSV +static std::ofstream csv_file("stats.csv"); +#endif // Return the number of Bytes used template @@ -53,7 +58,8 @@ std::size_t compute_triangulation(std::size_t N) dt.insert(points.begin(), points.end()); std::size_t mem = CGAL::Memory_sizer().virtual_size() - mem_before; - std::cout << " Done in " << cost.time() << " seconds." << std::endl; + double timing = cost.time(); + std::cout << " Done in " << timing << " seconds." << std::endl; std::cout << " Memory consumption: " << (mem >> 10) << " KB.\n"; std::size_t nbfc= dt.number_of_finite_full_cells(); std::size_t nbc= dt.number_of_full_cells(); @@ -62,6 +68,17 @@ std::size_t compute_triangulation(std::size_t N) << (nbc-nbfc) << " convex hull Facets." << std::endl; +#ifdef OUTPUT_STATS_IN_CSV + csv_file + << D << ";" + << N << ";" + << timing << ";" + << mem << ";" + << nbfc << "\n" + << std::flush; +#endif + + return mem; } @@ -84,10 +101,10 @@ int main(int argc, char **argv) { srand(static_cast(time(NULL))); //int N = 100; if( argc > 1 ) N = atoi(argv[1]); - go<2>(1e7); - go<3>(1e6); - go<4>(1e5); - go<5>(1e4); + go<2>(10000000); // 1e7 + go<3>(1000000); // 1e6 + go<4>(500000); // 1e5 + go<5>(10000); // 1e4 go<6>(1000); go<7>(1000); go<8>(1000); From 57d57494da129564dddf17ac7bc5442eebee2ec2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 16 Oct 2015 14:05:48 +0200 Subject: [PATCH 366/487] Use 2-space indentation --- .../benchmark/Triangulation/delaunay.cpp | 114 +++++++++--------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index 1f00e2aee55..164489877b5 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -23,63 +23,63 @@ template std::size_t compute_triangulation(std::size_t N) { #ifdef USE_DYNAMIC_KERNEL - typedef CGAL::Epick_d K; + typedef CGAL::Epick_d K; #else - typedef CGAL::Epick_d > K; + typedef CGAL::Epick_d > K; #endif - typedef CGAL::Delaunay_triangulation DT; + typedef CGAL::Delaunay_triangulation DT; - typedef typename DT::Vertex Vertex; - typedef typename DT::Vertex_handle Vertex_handle; - typedef typename DT::Full_cell Full_cell; - typedef typename DT::Full_cell_handle Full_cell_handle; - typedef typename DT::Facet Facet; - typedef typename DT::Point Point; - typedef typename DT::Geom_traits::RT RT; - typedef typename DT::Finite_full_cell_const_iterator Finite_full_cell_const_iterator; + typedef typename DT::Vertex Vertex; + typedef typename DT::Vertex_handle Vertex_handle; + typedef typename DT::Full_cell Full_cell; + typedef typename DT::Full_cell_handle Full_cell_handle; + typedef typename DT::Facet Facet; + typedef typename DT::Point Point; + typedef typename DT::Geom_traits::RT RT; + typedef typename DT::Finite_full_cell_const_iterator Finite_full_cell_const_iterator; - typedef CGAL::Random_points_in_cube_d Random_points_iterator; - CGAL::Timer cost; // timer + typedef CGAL::Random_points_in_cube_d Random_points_iterator; + CGAL::Timer cost; // timer - // Generate points - std::vector points; - CGAL::Random rng; - Random_points_iterator rand_it(D, 2.0, rng); - CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); + // Generate points + std::vector points; + CGAL::Random rng; + Random_points_iterator rand_it(D, 2.0, rng); + CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); - std::size_t mem_before = CGAL::Memory_sizer().virtual_size(); - cost.reset(); - cost.start(); + std::size_t mem_before = CGAL::Memory_sizer().virtual_size(); + cost.reset(); + cost.start(); - std::cout << "Delaunay triangulation of " << N << - " points in dim " << D << ":" << std::endl; + std::cout << "Delaunay triangulation of " << N << + " points in dim " << D << ":" << std::endl; - DT dt(D); - dt.insert(points.begin(), points.end()); + DT dt(D); + dt.insert(points.begin(), points.end()); - std::size_t mem = CGAL::Memory_sizer().virtual_size() - mem_before; - double timing = cost.time(); - std::cout << " Done in " << timing << " seconds." << std::endl; - std::cout << " Memory consumption: " << (mem >> 10) << " KB.\n"; - std::size_t nbfc= dt.number_of_finite_full_cells(); - std::size_t nbc= dt.number_of_full_cells(); - std::cout << " " << dt.number_of_vertices() << " vertices, " - << nbfc << " finite simplices and " - << (nbc-nbfc) << " convex hull Facets." - << std::endl; + std::size_t mem = CGAL::Memory_sizer().virtual_size() - mem_before; + double timing = cost.time(); + std::cout << " Done in " << timing << " seconds." << std::endl; + std::cout << " Memory consumption: " << (mem >> 10) << " KB.\n"; + std::size_t nbfc= dt.number_of_finite_full_cells(); + std::size_t nbc= dt.number_of_full_cells(); + std::cout << " " << dt.number_of_vertices() << " vertices, " + << nbfc << " finite simplices and " + << (nbc-nbfc) << " convex hull Facets." + << std::endl; #ifdef OUTPUT_STATS_IN_CSV - csv_file - << D << ";" - << N << ";" - << timing << ";" - << mem << ";" - << nbfc << "\n" - << std::flush; + csv_file + << D << ";" + << N << ";" + << timing << ";" + << mem << ";" + << nbfc << "\n" + << std::flush; #endif - return mem; + return mem; } // Will compute triangulations of i*num_points_steps points, @@ -99,19 +99,19 @@ void go( int main(int argc, char **argv) { - srand(static_cast(time(NULL))); - //int N = 100; if( argc > 1 ) N = atoi(argv[1]); - go<2>(10000000); // 1e7 - go<3>(1000000); // 1e6 - go<4>(500000); // 1e5 - go<5>(10000); // 1e4 - go<6>(1000); - go<7>(1000); - go<8>(1000); - go<9>(100); - go<10>(100); - go<11>(50); - go<12>(50); + srand(static_cast(time(NULL))); + //int N = 100; if( argc > 1 ) N = atoi(argv[1]); + //go<2>(10000000); // 1e7 + //go<3>(1000000); // 1e6 + //go<4>(500000); // 1e5 + go<5>(50000); // 1e4 + go<6>(10000); + go<7>(1000); + go<8>(1000); + go<9>(100); + go<10>(100); + go<11>(50); + go<12>(50); - return 0; + return 0; } From 6cbc6c7ea5b6c2194305a31a44bc2dae135e5274 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 19 Oct 2015 10:24:14 +0200 Subject: [PATCH 367/487] Restore small dimensions tests --- Triangulation/benchmark/Triangulation/delaunay.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index 164489877b5..e45c4f906ee 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -101,9 +101,9 @@ int main(int argc, char **argv) { srand(static_cast(time(NULL))); //int N = 100; if( argc > 1 ) N = atoi(argv[1]); - //go<2>(10000000); // 1e7 - //go<3>(1000000); // 1e6 - //go<4>(500000); // 1e5 + go<2>(10000000); // 1e7 + go<3>(1000000); // 1e6 + go<4>(500000); // 1e5 go<5>(50000); // 1e4 go<6>(10000); go<7>(1000); From 077e9c43eb8656f958c666822ce1d0ffc1315515 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 21 Oct 2015 11:15:42 +0200 Subject: [PATCH 368/487] Add missing new_vertex() function --- Triangulation/include/CGAL/Triangulation.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 3a713defc4b..651faa0ed54 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -630,7 +630,12 @@ public: return tds().new_full_cell(); } - Vertex_handle new_vertex(const Point & p) + Vertex_handle new_vertex() + { + return tds().new_vertex(); + } + + Vertex_handle new_vertex(const Point & p) { return tds().new_vertex(p); } From 02d4e438e7bc210a857b00fc37ab0f06945f21e4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 23 Oct 2015 17:47:47 +0200 Subject: [PATCH 369/487] Improve sentence --- Triangulation/doc/Triangulation/Triangulation.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index a9218c13680..b6a821dcb7a 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -402,8 +402,11 @@ circumscribing ball whose interior does not contain any vertex of the triangulation. In case of degeneracies (co-spherical points) the triangulation is not -uniquely defined. Note however that the \cgal implementation computes a unique -triangulation even in these cases. +uniquely defined. Note however that the \cgal implementation computes +one of the possible Delaunay triangulations. +The computed triangulation is uniquely defined for a given insertion +order of the points (which is always the same if inserted using +`CGAL::Delaunay_triangulation::insert(ForwardIterator s, ForwardIterator e)`). When a new point `p` is inserted into a Delaunay triangulation, the full cells whose circumscribing ball contains `p` are said to From a2c68681fed78e9908a2ba3747629d06d7338d8c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 23 Oct 2015 17:50:54 +0200 Subject: [PATCH 370/487] Change steps --- Triangulation/benchmark/Triangulation/delaunay.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index e45c4f906ee..a1e54c12379 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -101,17 +101,17 @@ int main(int argc, char **argv) { srand(static_cast(time(NULL))); //int N = 100; if( argc > 1 ) N = atoi(argv[1]); - go<2>(10000000); // 1e7 + go<2>(5000000); // 1e7 go<3>(1000000); // 1e6 - go<4>(500000); // 1e5 + go<4>(300000); // 1e5 go<5>(50000); // 1e4 - go<6>(10000); + go<6>(5000); go<7>(1000); - go<8>(1000); + go<8>(300); go<9>(100); - go<10>(100); - go<11>(50); - go<12>(50); + go<10>(30); + go<11>(20); + go<12>(15); return 0; } From be5ce06fe91cd110c5af9a4948c2d0b25b60ea28 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sat, 24 Oct 2015 09:16:18 +0200 Subject: [PATCH 371/487] Added performance chart --- .../doc/Triangulation/Triangulation.txt | 9 +++++++-- .../doc/Triangulation/fig/benchmark_DTd.png | Bin 0 -> 114568 bytes 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 Triangulation/doc/Triangulation/fig/benchmark_DTd.png diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index b6a821dcb7a..9fd8faf00b9 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -519,8 +519,9 @@ set of points. In the worst case, the expected complexity is run on \f$ n \f$ random points, the cost of inserting one point is \f$ O(n^{1/d}) \f$. -We provide below (Figure \cgalFigureRef{Triangulationfigbenchmarks100} -and \cgalFigureRef{Triangulationfigbenchmarks1000}) the +We provide below (Figure \cgalFigureRef{Triangulationfigbenchmarks100}, +\cgalFigureRef{Triangulationfigbenchmarks1000} and +\cgalFigureRef{triangulationfigbenchmarkchart}) the performance of the Delaunay triangulation on randomly distributed points. The machine used is a PC running Windows 7 64-bits with an Intel Xeon CPU clocked at 2.80 GHz with 32GB of RAM. @@ -560,6 +561,10 @@ Performance of the insertion of 100 points in a Delaunay triangulation. Performance of the insertion of 1000 points in a Delaunay triangulation. \cgalFigureCaptionEnd +\cgalFigureBegin{triangulationfigbenchmarkchart,benchmark_DTd.png} +Running time wrt. number of maximal simplices, for dimensions for 2 to 12. +\cgalFigureEnd + # Design and Implementation History # This package is heavily inspired by the works of diff --git a/Triangulation/doc/Triangulation/fig/benchmark_DTd.png b/Triangulation/doc/Triangulation/fig/benchmark_DTd.png new file mode 100644 index 0000000000000000000000000000000000000000..76ccd5144a875bb564a64e87425bece10fd43b17 GIT binary patch literal 114568 zcmc$lg;!K<)bL}42_b_J5;j6&Q1?#;+0+%Qq9$S@Af3m zF`W3@rZ@D>Snc|a)hmxS`cI{oT__s98x)>%((ij?LMn$oTds@TS z_{coSP3gnacE_a>syC`akjK%}+$*k{uk5(YqaX9V<688F{8j8U{Wr*?_ot7vo2ae# zj{!FcbIwPqM@E_-!eU56=KK0oRzuqUJRuYgV_M)HPo&bPop*s)_Fd{f@V2KaeJDOI zA}aF4p3A=R@o<3gWpeb1N4yCtV24VU;k5Nw*FTW}@*~@#V&Xj5-kJB)&NnHxXy#LCHbXFq3r9$#VjoAl$|MEHlN zr|C(jM6K6Z6E*RlCQpg`X5{qD6ZV4d}Z3?zO@z36*) z?WbG){Q5UJb3nMcf-GM(iAL{M(xm~W03$^1Db~hQnl&ua<~xh9)G;! zY{vWd-GfLBSw@NnffZjVW8W2;vF2jCe>TZMWH-X$<5O!n8oP zfB1i%LQ(I3L&=cAZj3U&X-nVhMba!`-IXC$r;WvBk%22>l0Du0ip-_W|FDr^xn{Wb z*p0dtLLgK1RpT|uIhhX*(-XYx7K0zec6ZCn)I@N@Q4}qm|M)~0xZhPZ$2noWf$pHx zS`+>f>)}hk%^?ni5{rEcc|uJ7Qyw1W#f(P`D~Ke?!nA%m8A+eTQ1e+aD(AQ118g}t zUiIg(_qrI!-YoI(LB%3jZyNsd0M{&M;jSp7jyNkUdajh3a6 zMMKe&S%~c|Gt3^g&6@gf=3xV4OsD)SA{Pn$=d*B!N9nLR)+UXw?0W2X9{+ow!!i8W zjonDYEBm9afYzaw(f2RKdKq4_&Wd|^Bqp7Tp9+6z7@)N>-L%#}43_h0PsodEiOP7F zxrFTBT~>I&+4gZkW?tj-8$BFYhIh_EhaGB&ylngOh}^+Ue%7w7Kh;@Vu=YTAt(k4A(>IP!}}R&u>__eK!I zlOyuOvw8f(e#1k+8rtiU&~}xvwF=x;J3y^_2#}h z8ms37_-|I|w$~!iAiL^(_a@TzVduck!w4&)EA++!rbn zR^~0>rQr+iq5E@prLHHKtDjtz93FxlLi3ztC?>Jh&LZ4kkSmDm9#cvkam1?d&^W$xVX1yp@-PY;pjw*{??oEGYX1q zm*QZ_4j1=tN!@)pwg>p`{-46E-X&R0rj$`z07tg91bIqeTR!M}1 z%50iM;zAlSYG13FT5C>%2fI>o8+SgNvwpZFV0$u#MyWkd=>l$e8FXZ z%08E6b*Ch38ws)ClL%VKOoWuywFyl04F~>`Ej8gwT8!6>Id~*2cA}W(lJ>;WtY%_g zrJHr%@1V)#twD?NfZCU(gs%?bA`_E1o4Eedi58& z8dV`bluMNjsEj6zEz~P2HvHTXM~Y#(D!zr5+u4(2b>4NwTYKX}Iyu_91}6^1X1hH; zP3OJXnIAs;een~$pcj%CJ`U(PudPwa%qw4S^`G}&fBO;3uP3~xhbxK8qR^=z%YEPM zXG`~-SHRFryIp}}PE`UuW-xOweL(W*_EGDzVBd%z;pKi-r^fa;6`5J28%DFDBXNT) z+u@t^Qq*4MRUPP@Mc?k-6NVv49ap1euL-=LpT3c%tFEM{NX5BttgkN(nKvl=?52E@ zbS>nmcl>A9KXI`7rZ086{m?R=GO#P3yZ- z_*E^X4K{qfNIIeM7q}`h-e8oJ+K?3cXVwxVZa!VYDs6Fd=wH7EJA2WF>XkiUno{U^ z*FmNkY9wfa_nbP5Ya=FP^0QHM=Fd9MWI>*Ul&p_jYnZ)zba3PEZFI&KMsyfri9$ zQq*^aK~57Gl>Tm=8QZB-!|NQBtL60;#HW~_Ny9+_E zp<|(#kd5wroDn9ncD*ylrX9xHk40{NiY>Ih{7LhACL3?gsFAz&#=;pfkvxUgg)`}3nQQ_)rXsmidB z5K_2PZvv00|H>aK*f0C48IRRePXrrp#QWO;CLo70J{4_p=oZFIOT&WrEfy-N$Y_6}()wH+%Wz7nYGleUuda4o7 z)ERT}-@kuf!tcDiXj49Ouee|a>=GY8KLK{o)N0AFV|M(XM3-K4tiw%Gv~7WfZELrI z?`(60RTc``{^eY2Yl}3`p8ce&?vm2db6_7{@zw0TL<*Mw{0VRW zQdLzo6;Ym*C5t=1xw(1FRAEp^9)cD!%11@k*Gs6W^-VhEkw19wI%#EjdAXfQ+s&AV zlk@Q8#PdSV64?bR1ZipMvWYjDbB040@jg>MNrD_=Vm^Pq@NSq*RoW9VNIl2ZP|6O% zA?i(&yjW-p(bw0{pSIbZZ7?x0ao-#zARy@J=^-E_%#MA;%q;M_|LNU% zL03^xk>GxR&F7F1IzolluXD@PvL^E&-E(ud)0kLAZV$)$*n8=hm6a9h*xFNCzj%=W z{U#I|3q^uUnOi%#XJvk#n3ndxm9H&Ih>b-B2a8|G+Q2n5273I=!Q;n1ayV+}h|%2q z7Heo|2oHvVfx%^1$@%!PUW1Q&Uz%jo#ZFywb8~-xKR9xnM%6#8hqA#Oq;D?E*xyEk zhhJYF^ridm)Eun#F-Ul+_dL;Iey8KACn&W0(kqo}ld}?Q+u4l|sd$xT(fVDI z$^CeJ7&Uo-T|{uZoVpf60jV=iSn!X@jjFajWEs$Ryp~TWrEV@=5qWJdsRV7bLddzY zRgx=Rmb>_^di6Nt!4RB#9h!Q)%pc;01GK}aL?T_J)V{xOP40kc`x)KA;UNW%Z} zbfqU*x1K28r><@*a43_zbj1deOLNLZN0^?CO<4Yf{!!larrwYy zD&>H}#A`mHBU!-OWyU$C({0Z0#Q3CPc6OGORh2WKf15S%_VGWASWMAIEzA7epCXK( z3;FRTo(!VJc$9R@fI)s6R@BK_A@^>d(cI530{@F;T5bOqY$?rd{|8r__x_LD@bLfVHUd`Z5HJRD z$irtOa6AkITjubD6$*dDKewMDy8TSm-KURP+Q={d=_b(CIJLe0J4JZY=+!;2ZhjHEJ!PWU zNi~}B5S4#-)(8rBP=3dZ;+%9j>_6*%@z$gfaNaHgdyHBhT2{{^7&4RBqR{hM)1*tNt#le63|NaxjVf zI9E(gNF>t4Q+5WU`#K1UJpQszbUhRV_FVyq$+8q~_|P3DY95OWD+x{cMsH7z!tuGs z#`^~>3n}Y^nu5E7V}()N7o}U$kU--CX^Ulijc$ft6{8^O5kWFy@!7_9C9Q_NK8>j2 zVK4^O3i+;P)Cu(dxCR6Avk_}X!UoO`R&Sp@G53w~zp!j2{`E~TyWYm*hWMn);I(eq-AsD1`qHo@Ms zFLl-@d9hIGzP@x?+J#j)Tg}S9^OB`K?C3>rYiV&Ncd7l=Vs33Q(JR&EL%&IBmuv0`cJqFYg{mv%P(N z0oxU0^$iUdN1MUCmB$%2;rlx?4 zP3pafA;-IO(%$<^K1UlBKuh?Z?0~$*IOdRm3(H!AyYyDlUHk2KNb7H(4>8rM&`(Ze z+=HQGpZ-2#!N-MZEvG=uMv6^MhswWwdw7H{+VuDLcXoDW@H-q(lfF9a72ln9?UQV5 zZ2a`;)7!Ui^H&;_6S&c6bY5OwO-+rIl+=b92$ej>wah5>Ha#+L8{x)++ABzLrc1no z^hPPhf}-Qcc72DaDJa?o233fnF-}Kb=i-RRL@_u~QM}wR|sy>GQtr zG*`UX$>lS5gGbdBZ6;;MrIy#C3F#$He|;i7Sn0WU@1F1BfC5Id*%J|3!Xu%hg9BwH zrOxhd{>0}NIDUS9JVw=D@yo8onqP*-#m8r7W#Pi6kNk>1Pl3?!F)NGtHXFtuU3$w( zOI=)DXS@o7sFQs93^~cG81jlXA(64MZbM9WA@X@L(H%|CMPj127c&~fz8UMt=gTC7 zYUrNcjW^B*LMjh4(B@;;be&$92MpvgVQ$5W1T-m9rRO_%$X_ERQ4>*z5P->}=DKg`6>&rc)lKub<;Sv3_V zZ$8m7T4-pSbX+B<2l;B96cG^-J7_#dut8^5Hi1AO-uU^Y`iYIGjvawSOhiOfHnG)y z!Y5e%?j2_Pm#&%G6UC5_koQoqal*n#Mp=r%zM;dFQe&JxsJdF5kYZNqdAlI529qZcYf8}F5wp+bO2><={Sr8$El#!kuB^_OAboAhNeSX9` zIKh&VlC410{`|?u$M-HMhz-5Bw|BHLVjh}jP}Bs0$Y=60GJbvZVO6WGtqq(saO!%c zqHJ+k`x>Z z#~m75fo9~ht2hqb{r&yHp&=kM`cgzmiHV8H$SS<{7M8mc=3KhDD0oaH+&8qGoSYK4 zjX}a415^I<=TD(wRpY;(_fV0lsbYTDXRB&bXRltqT-aOe=m@3KY&0G9`^F`A7c08bWQN^@izw1$}e8bCkfip5_W*H zLCkH95%n=7gr7Q0`ua4p$I^G<6Du_kC42M)4yL}R9hQX--;ZNs7Zf=#AtL5zor_;5 zqpv7pJ#0)Idl#`p(N90!yKWpdeJP&^>Cp8xxsqJXN@s&UUNYpP*bNY#uF@#$KPF+$ zbPzmy=V<2XGL!#6SSJx<^mQQmVaAvLuKf;-uRzjoPgY!{^ADAe|96#kIQ5FIGRcQN zz6o=X#t4O;8^STs{}wJyql+F0;2tF(6*s16u(eot{)}Sm!7kQJI5GVrx@=20j8+Z& zBA}N1BelULSO2vy<4*i9cy6V0ua4+HX_{hW+!LO3P3;$&XEWF%QTro%vB=OOD7-e3 z+RD+t&UK(q;m@Pi9JTwO!|_RxE@O?->Tu<4x#itpNHhd`zYywjyV}ula)9U5ioQZ$KA9sumM|5EcWop}wiqIphBrnPaTv&M!K(@4{fIYCi>Q5K|IgaK5JNdj(eo&%R>;` z?=kPN$iCa67kyG|qUKbG$%(Ro-HN0eMUtl^(WbAwuL}yv>t^%xQ~S~=nVHoM%EYy% zMIh_u_@^x9%R9=O1b=9UUR9@y_H)}2U?$IzIMYC%o4}R`Z}q{|K`tLlSV<>C;mwik z=ittNJFTAYLB?O-sA0g1=5LfX9|}KQmhUlFOb$M;tZur*dQuDjEm?h-3N+evEHql< ze4_RWk2U(L{tts%xc!*O^wGU3^swmSMRXOXxWrU`!t~_d-bSt+ib2>@3S=&UD-^zi z!LNs#5kLuhwz$<_6Dr&k##1rbabzo9Z>2oOV@JU#GIY%9s9)}w4N-{s>fyXiAIC^J z^q9PYY02ZiLC55VZ(H$LNS_a=k(j;O6)Fy0=R&#d{q%sj_m=zVW^yzX>BdC$q#X#I zVLA6$=Hg~_{RGm}tyODL>}W2ugxWR@6Ua6;7R^&jUvV1!#-=q1 ziHPgW6S;S0vAfE%rCxL5gfARP29KlC_>YiCy~ywZGPuL7BJL+puM2RPEN5e4YBhVJ zj#yk+_+#lxu;ozT^O<|rVY}nGGza2(EJ2=15_8XQG0PpzA&1+fY>P$hk4Ag- zo-qYE`mLnx)N%{N*1v_w>*Cf(jx`9wP)47- zG|)LY#fDYfjEv1=V`EcO;+&jYzoVD{IT&e6B#$i*!S_8+b3oR* zb$H-KYv{c0xq7u)b{4-y{(_ES`=}_m#Srn9KL~dOyU5oU2-64JBWY1lFUlq;&EdFg zXefNBd}(Q^6i2J|fCSIXb8XS;=7%(IgL`X#Ti@LF;){o|)m!aZ?6vHr%YC2HlVW|l z=4cNU`x4XS86Zl=bwup&-2A`jaA++CC}=`UN?*mDJ4#D8ZTQNMNF9b8;gE*2UieU& zQjTy)^czw{*VuSzb9){=N0@vIZn?Nt)szftB+2AJ*^t&x62r-UQep*ykng!QKJc8clM15Vd?Y(eoqs!i>5UX4R+WaRWHlfysg5L zykAzWZ*LsMRtNCIEAErmFrnCGN6bL2eJiiByZ;8d-t|$BIebhvbMqL=D56urq}6Q(YN&iDq~G1I zGnxftD4X#g^FT+5uBs#pv5dVe&i4~zdy7np)_<~5sI7m-V*gNPRZ?&~*BL^=)qshK zDt%}>n{t|$u-}^`5b?=4M`3I;!>3yOVhcbN0v=yf|J*Hy8Y?uUU|{GIZQ5$#=CLHr|IIKv3yvaotg#&^6>reD)V#YPI22oiAQdJT(u@d6*phY z`Uqi5cesw_^*;rO3L`A(p&`-(^qvZVtz>y6Z43;JKjYHew=(=mBfJD_M#a}@5 zcy#3m6&XIriu4wZf1ve)f zoAv1TiT(^3ZS#Da$tO60lmd;5uLpH$h^R!;CCZi4kE6JaeD3CFtksg5I*L_%)Q~Fb z4*60C&f^NfJ=hYv7H7qa)(=BDYQ8=`;WWakL**M&lnM#aNEevoNyf?8(gVFoVY~ou zxBG$J#}69Fjp=S|t~wo=fA2(LiOEhsg1GA9j(8M#_kla!Au~p2WqmiU(?N*7`W-1B zMvVu{=kmNO-y6bpyxKI0G_r{Z$4@;OHiKb&3^|tK={7Euu7E;n<i)rj@4prtl}DuL z@+3@LyuXVtF5g^56$bO1dL_+XcsBKNZPeJU$K83%VC=3tKo*5UPTN3Xvj0V5whEUg zV9{r4-D3yeV&TZk%OmuS*Qwa>G7pE*mo=Me4;~mU`c%-n`x+)}k8?kL(&aD4dt>8=3tb)TFNuElZs2B+St8nVY-r3!Cr|*KPS19Bf+w}Rc~q+ZrQ27P(#KJkwHoCH%XB zrU42+ioOmB!p&gUs9gQKK9mD0B*2R7`4Sb6o)hBZrIej6cJh<&{tZ>7b?V+UH+RA3 z;-)Ojoz`~QnGoI6y!X8ZBP|2O{jmeb`;gd$4lPuFx)WSj0-`>1uUK4>jVnN%P9u)N z!ZcrPaE$JI3BSVchP=3-j&QoEA1|=bZq0!hVKl-;*@tm=eo}F9S4i`Enp^rS9h|pl z?yftOJ*YL~TQiu^UdX{4(sDb}`{V0=^-!CE(<+?~{##BI){OLX>rIz-teOI-R@*}z zkr)|iR$(9mhdb0PlOwDh9Ck8ff+37zVq%<}&u7*E##2j^=%m~n&WlM;XK2^M)y8vY zi;IoTt^C%LEX*KerzcoQdxsH;!1%XIG-k2%K<)z$r?)ezIEOb=-Ls{hsQh~roE8+F;-+U_`Of&oW*b5D6(9yxl7xt(oErUsw9Uhj7gT4BF9 z!N5Q~hN#0?K8^&hF2%k=oeif?+v*rMDZ=hrX`k6X!>vJ6U)ATbi=H2C3Y#@U;2+s7 z#{>$0`~V!qdAizp{l5zZh5Z7B(``kmeQ&PL)3I#A2(X>BGgv>*^|jua$_=~bxZ z`^UCVpufLM>?U!8nb!#OXQHOSj)1ScYUwRCV*9<-H;w}9X+XU zT&gO|t7-A4S0l35HHb~N7!j>I&lw||ZPp#*(cBI`U`XW6#}-OBm9&aO=cu6uVklW&=y%(X^XnpzEYSta}MN$9}(i19(zm2f+!+ zPiz6`zjQDXhz~hgSpmE8emf!l_O1;%gDMAmuw9kd$_Q{ksi>&d+bu|KUbEjFuXZ-S z#Y<%qb^yTT>K3Q@7Bg$hD66Q92yjVA)ORW5bITNr)S7n?7K~7nlJa}~Gt=hKUv5Gg zCnU8?UC&pA1#@dK?y781Ox5IxDHeqZ@beE@mH|39r(et#$c%!(Om`Fgi~ccUh*fXP zTp3C+KI20uX&*+a%XIhk^#OnA^XL3aA~!$4CGO+n=MyB@AP}D?><9@6+!v$Rg_5~M zMMe4e2Dk5heGdg=tgcz-VP!rMP+3eV2nBY^AIq|ch(6$fQJMn@3aAX=9RmXc00YMO zGy@vN^zb1lL^9>WgzUzfMLk7mfyxJ&kEz0}l4isb`Hnj)c7(64@cKTdekn5x3yXxr z<*e_nMX0ud8w<;8>M36__gOU@To@5SJ^H3l#T}2m)`j@#(`|45fZfobgi2zi5Art! z0o^#vxbpgOvLMM$X3F#Ho)zSV$^b(W|42}ZS3gNU=BqT^WirCm@N|jE|FHbHy4pY8Wn{dt1 z1_Vbo8*gS3Ljv#U{hQjn(DZ+SBCx+GzUJyMQ@}>`_v8&gl>ImzM!zREH8thru$q6b zuC4|&2o(vYA#6APgomfEwN<9a32g37!^y1j^XE$`3UYFZ&mTcv&(t1$*DnL^-Fk)K;0;smY@5cdSB7^7HPz3@tRO*#|tSrKN>P>eTE=5Y+w2`<>@17k#!V zJth1K0>$2kS0y@uD$GM^Kd~wy=te7B-$3!yrbvt<+<7qMP7=bsGV zwhm#m&2M8Rh`hCp&b;AVyK-Qim{6MN9wAs*vdVjTu3bb%lgB-dj#KWoL;c6*4t}cd zvWjBOWN@!!=Kb!#5|~&Zu+&L`(h2u4{xJT`_Ja_FpW*-&~;jfMk zn)@Gs%gM^joV77!OAHTuf=It`=^hA4zE)&^O^I=W9g|cJ~ix}3eZYfA_MUiAnk6%=Jgt^Vb z(YhqeR+DdIO~DD7g4t<2vww7wv}}DC#aQ6PPmB5=+`@gQXa}iaa`Q?BY2b12`=4h{ z*sE`Ph=p~FqUR)va=Jhrb2Pd9GqA;Gr>z|Jlg7g6mkTN?nO<^sJ@^2}w6dF9FW058 zGmn+(ubMgar=x{a8$GTi33aKkRF~7WsNuM!lG?a{6d8TAnQ63Hymp@o_xcj*DCJj` zGvPG<^6kW{!+*zC!pYjmgFuj^(*4gtFUc-YJqDt={w9F)G}TLqoh-0*eR6q63mHiuf0C)*`O36Aym`FN_i%lZ1ecdeu$N;hK^C{kkZw+^+* zl{JzCPRQdAC<0sGS7?k{pjv9=9I4Qw`WsyI^X)fA&mgjj`Y+uj&iB+3O7S;>&$+yL zxyQ#e5!LI}KWy?I=a1_=3E15vS5R8~yT-;_))3lwTb*m;)E6=?u|LIxEyc(g^1Ft> zF&kLJHVD-3Zcb>O+W-eGn213r@i_>n_yh#n>l|GbgVWs!YFo#+|A;-rabfPkEko*V zqKT0-%BFej1t+>Y*Un>95I*-;C++T7+L;50h_Cp$Yx%#EgjugAToZ#gPvum1j=-sZ zp)C&275kfd7nZ=t?9_WqD|IvS*$cL$96?xQ%KGCw(Wr{%fVQRON>?0*yKzKVm_5h~ z&~M)hbBDLXqkrCnq1VE8I1BGt_m30Rsq##}`DHh38M^IinqFC?IZim{qU%bM{b)Ju zSiq;FB7MtZKZfy%Cm=hIyj-9CKGVwXvT?0Ho!y8=P6f^moDgntGHYp{TeZBq>+S6g zNDrNamy`aG2Z9QBhCkQgs`rYHrR~pG-Xh-Y3Hy zXx*s~G1%@TNSB08V~wuQc4z5ZZyt%BghnNIc=}b?r#j@*cTZRaLtPB@mck5GPAcQO z7X;CGweI+dN&I_=k*nCGGD0d?@Z;5=sRB*D1IG}D(`9}ct(iEE!v_uVbzSMCH+C+w zR7}EZYhXh^Qof}TWkTgs0smYyF^P8iY-++WU^>(J`Vdu@BygV;SfA`=nKc{Tk@4}z zKxQM@cIyv%K|oHJbA@KTN_x?kk`ohP?6`lldp(YGrj*kE}vh+J@*+utG*4NM+y36I^$v&zauHef8@2%5P*N0hf zvYq^{jhW@T#u=Yb4KZ6}({WgO|Zhz^twnNQy+^}ft1wA}>QuIdZqq=?e%e-RU zUkoBqTCBfrwyhK()0a9y7F{~PEA;|WHG)BU*6c~7tr8nViHfJErr!O$q4J^fuR_1N z>kH#N@vI#P8!npcQ;}B3@s-ukO3?%kO2SFE4mOj#IVkvz0|I&cW9bi|s42efza`rf zdhWjjb#Oj$Zxb0{YDxe_T5(%)>eqF=8aDBIWp*X@mV|vu1R?lBmjeeKTT)U2%I%xo zu4jV-Kg- zR*0E!+~OhM2gM&2K$Htn$>rV6vr&E~fnG(lcu2n9ZSu&nb5Y07x6T=T<8OBDmYJ|uX>BU7!TSK!drEMJ zf#hR$$!g8e{&agO!Cfv0d7ZvG$cVQrjYouExM|FV@+3Ty|YyDkafgBjGf*j|;9 z#Yw)8)vEW}g$cG~dNMPbXV0Xu-nhzMi%?Oy8j1_b|IzT|YN64a2e&R$qc4LCTk;OF zp9XAdPys`L)mP9MS`fS0}m8wwYd{9^C)GZxbYd z1VRz($_(FodpR1>+N~Y*)tX)GUuc<8xUhI0)3lhFp^UNcJ z+DYxAl$jHE(T;EGS}n)SztO1D zPwFc=y$|080PoFJ=iN=!KRB4iG)FXJ%ND(qIo}^{BZ=X;U4X!;hap4mlpTDQHmPo# zhZ2Q_t`ABfC`zNlinR;}ZhN0h>Z|RR&GgR^_^Hm@)A8tzrVCkom(5?oKQn!mGIX7K z7;9<|BSr2=obC|e^kxeeGaUAm&r78}LU0U6lp7d#8~Ys$eLB1ID&d14h@tPH-zL39 zPo|;p3UY9=Mjl5#W%FA-IHJwW+DcD#X*~}pvhK?sN;EV_DC!m`TKwSbVK3O_u zRN#Y9TV2(yS@BitpNdn&5#_XpKZfaqwZ@D1v>A$KT~CeVUk9EX;#{2iCclr3+j^|w z4FZoT*4y5&^N7uJ{6OZXxB0{6A@B(EMUj}RTdOG2Is0*|{?n`rAKx!wap|;LCBwi6 z<~FHcTUJ4 z)Tk!U!VSNM${lsgINUkI3M-&S9xgVtB=E&>n%3VJ}m}_nvyGtf~P(cII> zXr1axW5s?EagV(&R_W_@QQseqbxJ{E+Wx9#`(4@<0R(qyg|>u?y1V}a__((dh5=;P z8LBqQ{K(j0n(^?x0yZ&Hup!gU*z||l+qReM<0a;xMNwOlTm!8entrxk5Hh7pB@t@O zkh(qhDQa5*r=6`XkCFJRgkNN~5dnAahzV~A zH*RvEUhd!n*8rgK+()1hDa>))*>1TV%Q9xKO#yq9;2@#2v~D3cE~q7BbAoT>cw?O$b8`|~R}e(H?k7zf^0=i@`G zjKK-IDeW0;o9mkYnDm5XCU)5FIUnr51t-5F zxikV-doPe(2zjjhZw2M$ZlG`lqyaFp&8e#0fT_>;7!aJ5rg+!uYK5m}V+wQpK4%&T zjz;~j&}jZzkG=^8e@Sy88=kQ6PoEre@2yYQJR>tU?h+Sf^*8Wv_6hl+YA)V{s^LII z-g7YsWI@M*E;c9x1+^I)FXed;U1nfIYvFX$e~9GJj0wU~W9B-4QPr8-aD3X|&p6k$ zJDr31y~1`ZO*&u}fVIohJqtgoto}qx#p%PIfn6zVrCJHT0@XT7Hd?Y>AGD6RiDI9h z%TD&o5I^;Vl?b9;_LP~DE1Mnm-RWtRHSjgfc72${C6w6iE?k-z;lkYLSnUSTn3>Wu zP4AHBbND2I`=-O}0TYE&7?S&wkIgf3`YM=e*$kG6*0p6+^(1ZvN8J!>Ba z)Kx}CrdX8_(OK=Wyp-l=TK}8UTF?$zc5S{KX1B_T5g7UXGMaV8p?sW9a!SC<&xirm zLS~80vz(fo{G_lsdU=;vjKxw16=06H|6xTEL_SLqK-ggeEkPhH8r#*gW*TQ6l25Uy0r7 zj?607Rl{te2a%N)9R2whMj-Da)EDW1#u1x_qfx^VFbhgZ;DetIGgqCOZTh;HG=iIa z>vZjc6=yHr2T09_N*$c_HKo-*Apd)`JS6k(N&@Y+^8R=(u?1y)H+~Be5!uOG_V6+} zcd=KD0|h<5CwSgT1cCgWu5op&-)pbiZL9;$M=o3$EC36GnCTC&YexhFXiAq3@IOCX zpO}~c4Mn%?9uTg_Xux;8FSe_=$dwHYCP9l^LQ0C!F)7qVkR;I6W5I5cHKdXRk(Sh7 zET=^WW1qS*GFC7RxN^6#u`x6I3liaJK-~w-q5FGf42>=e!etR^H=d)^4Oh=Tf9{Y6 zO0ISH#6ddg!C!lSM`Y8#r;ge(I*G1Dp*KCo78ky#=i!NA!2S8%Hu4%<*>7J}MWx~D zcnY+C0ZJw6ZUkB$O`H5B(dBCCQXX}w&{9BSfN2mx#s2{cXlon@5j$bRvwD?w6IUm5 zb5)L}@ZbD>5@i63DbRb%`uWPG&4kI6?8~?=zPOH3Zuw;KH#l@KgZispaGKGv~jw`T%iK90IUn>M+xx_fa>{OB{>F1_>c`X$)Y&i7P~fnyvvWkigOni{d;|2Mw6rP0T7Y`BFFidbhLoJ#ql3;9yiY(3 ze+<*&A9o#GoU7Lz=Y-MK3RC{ut)Hev=-<8IgFwT|kabdf4T7DC?_c<@SOvR3?&?cW z-)kq-ZngpZq-eI81QooJY7l*Tbgg^uyQoRh%@-k_v&jDGdRpNxRKU~#9NsC91fCVk z?VG2=WjuDGb?O>3Mc(5ajD-Ex@bnkvE%GS{OPeCTUZq^Z93T4h}{Cy)Cf50?d?K;_q5R z55**TQ~#&f|I|;%L1Q!9J$QDOU6M(YVt-{v&c?iDYs-#@rx?J0Ix)B3c0xq7B9XlD zF)^)_F+X4I6U>TVn2P3vf5E!UWc5?GBmJqP$X;1bh)YZon$lQ#Sf#B0p7@zmS-Yoj zAQwkYR`l{qVZ_MGm6a6)+aK)Wvb!BRslH8G56%;1r=`-BTI*ACF>wegKehYN~X8GBPp?OH1$$ zjp*%xnQ@Q?FUrWuqKb=)!I|*^She(J>swQz97=-8?wDY=j}9!%({3TX;1KqDr;53k zmX-qR5WVRG7@$Wo3bOi7V?47SD%hiGb_Np5>C1 ze+2^qVZ804IkEX;kA#GdgNURkfkOo(ouq^WaCJrjj3DPS08uW9H+%Cup39J0*um}z z<+pF&hFd^GDrhwXE!0WVigZCV35$6dHG7a^P5*jsK^wNW(CFy2gPr;#@(}yszubPl zm80&?t^?W={aV=`z`O;R4cwnj(x*IM_D&utqBv#R_0^d#@?(4ueg2#v`4WMwZvKw{ zVx#Na<(u)W5{lgj@4vkswUL6f#&Hd?m~QajpoNEF_l;07bN3kSrQV;dkAaU!?zo4f zvKswUF~pkoA6~vNC#|B-Ln?nzx_+jK+Q2#id+oV1t*@u2XJ8-({9MpAU+jIb0^VKP z;01lOoSc6;I&uPTu5a79!OLu}uC5LB_41*VFf=Xi%U>XK-gYCGmzRS^rjzxd)!NZa zT+xI(W~ln3bu}gHiNd5|Kkt1r$lo|y4tCVPgM-`VcaZo)JRbUfrk`vY zUPh51@3u3v_$dOtlk26X0ej2uag039WVq6@t2nV6`kO~Q!wm5p6uiqQ$`5(F9DE(4 znL@mv>F83d4{TNQThl~Z^}ly=+`74{1RSQvZ|ydOva+^Ng`I6BXkAF|v4ksnd7Xl3 zfNt|&lm)uQ^dMq_4ZJNE%F6|UTGT;9N0Nj$>N?)W^@q*STR}r2U*9h#0WQ@M3Hmy< zIJFaYy}y6!mA(RR#{onEWM>SL4*^u79_egAmVkI`(=)B&oD~wp<5ebJ-8P3R-a|{H*E!%H zp)couz6UNH0kr_=ysh)$!cDdQU|t|C)#NV7AK4o-yXQE*FJJX*KGg4rOJA?KQlm+B z73(bMS7FI=^+?0Oj8%_mx!jt7Xa4st`xk-0Ri*Jm2t7EQTLEi%$+Z$VCF2s~xWo16C_cbG@+ zch&_=p0tIaqEtyO1$JEf2vi6+;4bY_#$}EJ@l4Me(-_pK`ZJX1U}()pIBy~72e{uw zuC8m|T|HP^Gt9|%`1W6)N=AwkKl)}f;^w>q=VrZ1_u|t-EzmX*RtCD$x%3*kUk#_F zjq^13DeE|7KG!z=l9E#IePGG9EO|0L1kyhY^?3qOI(XdU`>aZzNo;m>r_t)Kf!Y9m zYGEw3l|rvoeFJC4_{*kZwd5BwhPjcO*?q^^7!V9NWM$X;>Mz>#u|?~*n-Q`45J*Pt zCjcO%iQ|KrwDfIyi++rYU1c&Tb5@GiR#A)B2S=)(JwigBfan4u#M;^#c<%!rMrn>j zba`EF1(%Vkd7a*!-J5jj+4_Gpon=^+&)0}Nl7fJABdvmmZV;qPx*HUvyFp62 zQyOWI?(R7#b&Wv}0U{{D`e#8c3{wY-g!fi&kQ!FypC zDkg0A$B@^-1$>UMo=dLvWzco`*#RO5G6V(~87@5gQn;*lG>(s!aIRq5L~OBATVKHh zG~J2>6JR1w!Y2Ak=PTyKrdA1kXJb*16Gis)8f%lnX^;DW4D{V?a93CcmY(eu&yvVLu{@xB z;~37fYJT)%K7xb_@gv7sZ;~OC;itsR3#)=ZYMk5BdAVZdbg=f8OQIJxU z!Et9T_ew26-O}I2#(DYYP@Fbjz5yCYtvc+EfgKzCD8N+q;$?!1t1D+|+?Mvz{pn&j zu7&@Rv!nNY2MLp90_eSYHeSrEy_P048eW_((pmqS_W?7$OX2LQrA5RDE!*;I3d%!r zM2p8}rP9{I zj{Z_H4_p~W8fyLhg+AM|znqoEz0L{QEdORlZnM&p_A*954xcVJ7v%}qiPUe=7H7BJ^70kuYmXF5qMdj4&mt%ra>lP6ikB!6|AGs>M7H zY{FS7)Mme2HAPqxma-Ypu-{sse&5*rS)t334x;(-H3>W{1Xon9z5#3ZzPar9{j3}# z#llu5Oi2%Ffs))}*}0sf)x&V%S(hr#n$7tc2mB4OqmK3c>k!3nX938+pTm0%8X)Y( z_E$G9Ny){+VPj*|Gbf<9ptb=KV&}by0&vL>z@`o~(Z9}ZCc*UL^tT0q z8&Q}WMuMB9`wv(McJJ%T52+8&hO%)tvE>%RZP1B4Y3S%z{3yX_6w4t+1j%n;mfBh2 z2Hzv`e)pn;N=clUA#rvCgi36>-7>3H4`(*e59$XpT1TjP$T$r|g(G_dn*z>90{cMU z?cbmhULqG4H~P_~;!^|au8D~W5H?04cM+BABixj-7n=+8KTCIxjh`}Gu3F45fJFcM zAw>%WHOsBBYqFl`ronFsQau4T?$heKaX(5~!q@(;Da-RwSq>!S-bM3pb`MCaS*uQ# z=1;;wawZDx?NbR_cAew;YG6qpE~TRX3x{CrbU>vzwPqp)JImiS>Dy;WMgOn5JB+KJG^WaH0Y5L%RhzSv|snwd*q6 zR5{BfpW7e1{cxo>I^Ku=&kGRLYSw?!i*(D)z%&XR4!vQY5z#V9vN=>z)*@_{968#i zEw(0b5W}7hHz;Lb;0ZUqlPe(*V6ot{2VNy$Amp^$kP&A@Zs&Rjb~*WyL@TyQcacZ= z4J&6g4*?TKUubk<@p zgP@}r^~aB z@siEF_L$561+qZCoT#D@pHGT6ADN<*U|{|&zc4=H9Skdk2gi&`ENC89?r&5&x_^At z!L0NR9>L{Faw3bnqOYE?b^p#RsjpR5?7oBef}~ZjS}dWm4GjX(2klkhCIap!aH)&L z_EYSye<8BJ8cNeBc>gdbazS@>N>5N4q^hEN#zXe#woc{WO^*#w4Ijsy;)2Hsby~0b7bsY_Ud%NM)g*Mk-5;ld7rl6& zywPSb3s;$->)cHEHn}=qCR$_FI)5sxkG!*Ub?3ts( z=pB1{>h-^Xbuc~eX!!bt0Mv#PWkxP0@_g7lW`?D|5Xc&|n>imsGNM_yM|0ArH&&sG znn;D-cCAMRHH6sW!3=c2MPdfdf~E0r1w*fww+^brSy7*FM?mxD)v9z-SUXNgd5i4+ zT$G4EJz38tMV!s%69&?lnGp>u{sJ&hnftfYBV~%rrIcN zJTjlH%pD=q=EOI;Z!z5Bl@2cXN7j)o{jo7N)$&aelS4Elb+p(onvtSxn3chbgy{0G z(4tY;FgmCRfc4H5tW8zwI&$Z`ftHZVV)g>f!KY?IyO4vb`1E-v-Vp4ug5OUE-gW;@ zN6cNsUrfS7#A*5X61A74-irG~=3vR5UCDIDfFSDEQtSsT@Z#LMi_3*oWt*^iHn@;v zTh6r_><3({F}#M4=Ah24za_wy`<=@hgDuVg$P8#NSb7HsttRqEgK%g9utRO#W!r0c zdS-t75Z7|vxj8ps!c&ckfv1Gz{G8yvS;zP-8UF&quhsLPHCvTffAai#na2?b3aLu% zg5%IoONc@A6TpxJK(hZ@*{P+D8@@!_v2cl zaX|?}FX-!QuhdCxUAnvV-FO{aNo7T@ zI!fSNCa#YnieeP{SkLVFcpLjy(8B-ga4;P4e0>Ll+-~rC4`8?ynrQ-GGLT6EI)*U1J3pdfv3UX6+^Qex zf`5_G5osL#sb|TxTN>(VbH5-^#npTzy3>p&jv~pgh#;ZdK&gTtSz&M&;=o89bRPaz zQVgCEX1AFxAUbl%oxAU7!TphqHTZ@KJ^&wg>&_1=qwioSElr?tIMx2hp4=od3-XlL zyzR|LZZKi7)iPURab_N&?AwJ*{R6imj=oip#1?{lsPYtcbD#{v1l|iMp%8AKJ|DwWmi=wLi`Uo z=+|)ETs3Qn*Rx+Esam*-mD0?0Bk*3Vg+gWRP1h|L+5fS&=&F!3XC)?uD6E@*M0y`> z$&tiuxsaHWG7pT6;KITo8TB?fc0OUa^co#v?%1tORTbk>!1xV|hdTr_JSj*!Pl~ zIEk| z#=-)TXpko$v|~LW_S!)XrvrZVK3CGzU0EpzxlA~4J$rvJlR6Btn*o$ z>2+PMpKYn&O;=J7TUI?u?~m22-Ueyd1?8-U4iFy#SC-e^ zA&&$pILL~Mn3eElr{D*P$-FOemfB0trsug-YyZ64k0M4}O}E&*MraL`cqK4T+)Dn> zPmJE4CHIe0cq*=65VL}px10QL^%ul)10U9)CR09>r_8r zQ_RDzduv%<6Mw2zYut^CJdIRBLOe%M>GXJ@VI!GEmy4MD;DpNLh3piK4=n%!$bur3 zF2DiQ5J1uUlR$Mp!^ZQd{*HF;B(8v!D}`!%<8zbjC zMXf*GQA*-`m6Lgo#}e1N7?Y@uD(wbpYiEC}P88JODO!_LEsU-91QaNA2im2wOJ5X= zQc?~_Xd=AZ&<@f|pr|p26IN>feI?RJR7l{KCWBe{Siy9ajmkn0heQ)vCY;pxApb@2 zA$e(C&s}U|@rMTvHOGdF<#tYWrwa*EUM*a_d9~^va~L3DTF;bIF*5e`^lVS6=>fP@ zR$owqigj3^&rj599{0cu2zU>%=Nqpk(&;E{2U>oR%1B9o6-w4B` zelf_&->xRnyq-<6b|k4w<)z@G88cjr`&03-6W18xls0CzQ6ZGlJjwPmc2Y&ceCJB+ zI4^N6twg8?$!p(8O~sNe5GEFu6b74-PAnnX*t#Jp*4n9JI($dBz*|cJoXt$g2xD@H zbOhGTNGK_7sc^{pT6l#+h}*h1jRZ2xFeTWk)=YFEOy$bTN79|8)CSQeY|9p^Gew@7 zPAJ9n9@sxz2&l7_@d$3W|LKe~1inh6pE#%JN(z)C&MbZIk{WcOR?RK|QTZDN3DcIK zMv*|{>U@5cbd8iw5z1L{YI7v}DWS+bwI@+bDxcd@86y$jMNz%ywfWB(bq|V;cQ_X+ zI0ZZ{ShtiyJhNSM_TnonY>kDX%(x|#dW=_DN&y~MXNM)t|o0c3H0&;{{&xP7?0GWkJm;mC7Y z+*Iw#8u#-;08NOv?xpzw`!}SZ#3Vy6o86Y`;syRV?J18D1sW(kLtus{RF5FZ?d&d_ zB4_)R0HMyS>a;^6wLqF8{XM2vj8}I$&X_tfYsf;H4H3HWVv=XKS>T#3LINBcnM#z?Q&CR?^RpDSgJdStI}+-S1xyS}p4|H1bE~>t z=38^7GAoaz&OaGhs+Y%=l=kc_*SHC6q<&(OD|0$p07Cdj3yXcw6rG)!q1-O`tTtSF z>!+b!6Aov7Nf?|u+VdV0wdWEm{&?B>GF~-agk)@Ke)cj7rq+N;#EIb6bL4LKcONEV z0*dd|gi2R0I`vWrW;&+4PWgk=$>IlR=|vwWT^e^~SO~b;4)6qKsj`r)sftcqMG~Qc zr68mmw%NZm6@oxML388!$CbEYL+s^ypU(R>Z+-=>+3MY+oFyb1W^!#~Er2Dm1j)w5 zn`u^GLMUs^wM*WK9!gJfpg9uQncv(zEJIOWyLnoyD@(@eQf0|tf)v3^oV)Yg_5J+; z!Wi1!lfTdcXKJPzv*mwPVG=G7K`D*z`IVYy+g(C=)|w>M%b|Pc;)bnbjLi)%8|4~Z z6?BMnUe%7IuE=K-!Uk=GyjtIi|bHQL|R2VP777Kq>|EFNaD56 zU+fjgl=TWbV$&920N=&Xm>P(%vL|K`f0?OCoatIEn@2>STo&t`Pf^rv>cH*Yy3zJH%-akkSxsO!q zCgCNd3Ic+H664~yfbk_4Wfvx zj{B;5ddnb@#@P+g2c0nBFhGI~-GEp%ko{1ofQ_fs>!AT4;!aLn0F)0q%3c_(p|i8I zsi_I<65)jGehCI5*l|C?b{3pZ*A6$e!cD*I`t!J7yYUM%c?9~1G6ebp3iYA#aR z&J?PPEk9)uV|4XUdHWOFh|I#Lx?Sbw<+cX(U?`XMqdUGE-}q?z6?|{rfxM zCj0dvsnYp)NzdyhQ1Q06wh`=F@Hi-usoH1K_O&M4iH-16WDCqb?79xEL_^TyEGW z38Y2g;Yqo+69zv2<7!Iva;uAo)1`qbjs@Fw6W}yzlD_2<%FF61UXFAKF^59@bGWqB_qnp>4XwLWB=aU4%eiNrk6TpeB7gX zU%gYxo60G-c~aC^O0Iw|M>zf zlK*~=lfBU4JyU2y7Q9d7jh4-!FnLN`hxzTC2Y0ctqs_iM#@7j^;Zr0eANQ?{g6~vz zFto?82%NC)$9__Xko|2;j3umfFP2oTUkK4P}pP93Q9xIS6swwi;8Dl5m1 zn&Ph&fc=_YAw4uGNap?f@m&W4!y?rZZtI0!Lc9yDh%-_>-;lMg0+kiKriee=cjqR9 zIE-|4N8M%fj(&<9Mqld8TS_B7U@9^t*>gr%Q`oS-Ta5Qic78(q9jN%R9a*hJ(}*Jp z+z2^A`br}9%b>5#H@ZOGS|__B;WHi$8-$=w8!KG}w&AM$Hv^7hB9Bh-ie``X)+Kwl z@jt?N6~)=4Dds)Ayfo$gLTawAxtHDMZfqI6$}aC%4a}}Te*KA0jrYO6Zh_yPCQNaz z!S}3Mt*DW2hgZB$wrKlMl_0hs08CfJIrAv|gES(WNCRb}4>R7^}S@YcP45u#e8f-jkx5*G&;f7&3yD4)kX zWBQgjJ1a{f*JD(SMa~RRFI`;f^REiqf;ehGw>IHIRE|_4)`*XaN{lu+<8si))M&S3 zwvn^SPK&2tVRl*I?fF)=HdYX=#qi-lMiimN@z&v}>E7Y|=O9$7SbJ+jLwgWpj*P@^ z)?F^uX`G0S?VJcr6j75%TcRg9kGpNnNTk=W{w6Gc{lmVRtG6``U8iNcSiWd?e4#G9 z$bshESoUQtjU98zVN~L4X=*QH?Sg&6nOWz2KFNk8mza2U8|h#k_7rEl zC2D;~{u7ZSEKR9IilYcKGBoll9=2R{6~?w88yg!ZXVnJgzfejqdw`wlccaX0$J2Td zoAlAYUU2PB`Ch%dvlAc~ocd!K-I|4YcoML)#&>osHCuvo+8{~2iv%K7E+$w$x;y%2FF?74f%%3xCgkvmJ-4G@cFO2C! z{#YKo|4L3nDQz7YCQ!yAWamr*slD94QB132ka=OvO65q$Y5;IgSq$Of;dCZ{sGA6j zF;4eHsHaF}dO5SJ(vGS!CzDk05;9S0MNOcz**tKVBe@1p$n= z34jcH`?gxM#vF2Twd_rTj%Z?H0uDit5eMHp1Q`_-peeFrg*jO1;N!!>KK7;0aQdjT z>w`Zz1;=O${-%dV6L?!Hw5Ng+V*!AX36+Gad=RZ<&mKN|l13Mo;)R3JliCl2WCvoc z8eJ?=1oZGVh0qG%PtHm6RV(uJ%2NBeKhhR*-Z;x*l>PsmGH?oL~&heVw5B&;alKjT_qL}e9Lw9y{x zc?{0lHx>jfHOIZQDOzt;EOFX&)v~@fQ^fS03oaBsQ|Oen>-PNn1W}{VD9v6b67@pJ zJ=;uBXKLbL4j>R@pLeokx8AY}3e&p|!yQHhumej=EyYNR#NcNVoJD)DqK^Wl0O4H{ z68G()G;kyU5W!?V6wrj4fI|duPD3jIz{Gxt1O$0Ot{;5kOOumatgJ_%ivSK~I!LwU ztR3*?21Ei&V!*d=K(bLKdE05yZD=mXfL`6$;Gvw>|j^#!ET)9=1wH}R{kBmiHE)LJOPE}4wQ8`DdqwdDev$bGB}G=gWP#vfUp=mH5*=v5Eu5LQ zjcGFKq2gU9iGR?SgrfdsVP;ZL(ojZ(Wq$Q)YojkFJv|+Sn!qjO1Z)!(6=usVLR7R2 z3_;I%{X*q}F#z)&x+ze~BQyk51)xQ6Z#RK!4>vbAIOo2E0#A-K2)sue`>U*moTAE? zz-Fwsx+V`4zF{30`;p;~nT}jr$K}QKJEJBp{pBP9Qj|UAY2V`Us~!o$!(uojmhrvA zfW5WU_t8Mw?rbtT(Rcsp6o_eb87_tYUm|&4JHn{CTM5{>t7vz1eEQ zVu@rVD>}u~*U()ycQ~M-q2csuzbHz7pkL@)-8CVMFE%Wl*WCh-Z^%D&P+c1VMK1ny zwtuCVw5y-8RUqGOIQ|Hs+4jd(kYx5!p@N)P842o^Ix-oSY@;X)C8XA|&6&fc2?m4( zumg-t&AeLZcziQ7j`n*MsTg@AkHk?B;GaJWS9w5tdUSsRcO{^pYToNf6f)$3%OxnS z?N`I-_`bxUhI|!4{f#H!z3CM^h64xtK%)9N^*vSww3mR%OnkT$Q|OF&QZ!*To|7Y$go7nWa-(6+y!u!KCb9X( z+_567!teuSlJ{dVC@_34_vAWD%Z)azJG4APd(kFT_yTDZfqGBSy8LkS)xqxD@0N_i zoJW=9Ne6vWMo^CTBLuoFCK^(0NeA7)RIdBN&L|@t*R>nse|iuZ%G#q-aYbbCCoc9w zb%p^Nj-4L9yd}#_47MU=4tYIPa5&9CFmvEEALI78clGkw?#q4BFJu30}}s zHW)fx{&STsH`1RYjaFB8tLEr968B>`5EQQY@2dC^vs%9=#zm4L;kT8tx_pFOQBi8Z zZPax_p{~XZaK0C!D(7v2M{rlllAzShe#82HES*Np=|I57YT_f&?BvgB4%JR-B?$>S zw)N}MzF(o1$HW-(P1W#c2r<1%&lY6BEST88C~M;A9aR7&OH+FBJ35`ndu&SsZ~ zBf_Sd4i)UXSVoi(ptpC#bWR^z4=pA+>@{PHZWV&7P}eWAVJ(o5F2v0 zx57mvCS=_z9Jg!c7lB9kV5XwOpaPUWxzOxx$XBcF=w2mv+LB*gGf7jW!o7U1 z6IH%%M04=Fy{_hKP9)qd9(c0(i5%=aO0%XdLT;3>w*$eFl2RIY!DTFmxz_D_<|9RQ z{sKnkLJ_mL=&LVh?fDnpQgpvIfAj4vdFQ&NAj)TT%d4mja|0p5brib_G}oAG-c|Ki zJqujv0usAR#hdOn3&Cgq9PUrkyd+6-sMPXl_3qq92kix_`R9H;dC(6_fd>z_tvPiO zWK}=DQUcYlbD19(?E_#>;BL&{rYRvvMr;F z)qSqLo7qC&B0Hbn^TiO&*S?8H`f?CheLcLUWtgi~(TkhL0V!nUO8N$ zldGDKjSBshZ#@+$fb95r@TBblhcDC4ZLFl#x!I&|ohv!uakTh8;li=^3QJ zY#Sl+NC*(CHa1UtMP>cOAKkv}BxMN0zGRPM)I|&5Uli6T;`uRc`qw{k)59X zF%p!B`~EM&SUgAzsctE7K>`9P!KlZCZ5O;WiFx-O6F?`# zeegnF_2>u})>Z9Z?@FbGz4Lli!65O4j*81-<3I<+Y_`TTH4n>5&+ZqxxQ@|QE-R*+ z2sM{7J&9E9eN(21#kWmfCpzL4NSohbowopaLcCGIni*GvNv`}y9X?p9Po1});wp0} zsgNPT^OSa&Iccz%KdWG;saDRo2`ymoWr|MuMO4xi(w$m_zb?82I+H6gMg%!5O{PGX zOCDqFN$<>&D6o2{vm|mQ%;qWg=Xz03Eo+% zq`1!F6XG%`u!ui-{O0vf($Q5N(GFF0>GS%}{^AX3j-o=y4U#E8oM#|KsKuSaQd3h> zdhxnzX?`ns7m^Iuz-1CDQk>06O{3f|*L>Hb;CW_OZk~PVs2OJR_e0QMzUP9y2>?d+ zr^^5i0!XR=xn?ct(}SuQ-cAI$$V}zE33CPMhwY zg)Y2;UfzCB@b4t4PeJpGWaux4MkO=f#KHW@AYyt65yvh&dPBMxs>jT`>`Gx>FCl)$ z1Z={&E@y|b{-18_f>rkl6MH5>sb~dxJ}^5aZ6<^+3h;(j5S$uCixTC2b_MG4&bn4? z1%TuEk%cd4f+vnzr^1@Kj6x9igbEITv^u-xq=C;vm{S?@dxl0M977Zb5ocsdHP_%rWN7Qu*b@*2{Brw1J}4F;kC~ zI;j#2=~r>X%WuL(QDg#&A2{tEGH?o#Ua*-w^peN9)m<{=_b~0V7vdwL$ueUG3ji@C zhrIb^%_%v$uu_{kk|@KQEGe*B0R;{KO$JK^cY6W1^BoXp!5-Cr6Ohg#c5%vp>$|(Fqs4hZX9n1FaebX;H!g6s1{Xl^uZ_;fN2A$2 z%w*@T|FwV)cpgoz}e%+RY7#0V9=OLQ7 z7vefyw3}WPuQt{O--eG2E?*2pIU+;H{f5bVVF)6NA=tRiq8lDEcO<+Jg#3F%m(~=$ z?o#jsFcCjlapQ>t7L%RbDS*#`r0%cDrDN8^-Cf2!44a@6FbrVRakgBCH6MPW$c+MJnqTj75`ubbsbOg|VqHZE>5 zmQktm1@w@4uOdLeseMSZq!!fdpp0O>*CdEjM8q))?xxKt0n#9(X{P1#VPU#t2`T6* zY@Mf@$&Ny6hiY}CAF2EJe}N;9n_KmOhB#)Rl9c2n1u1TFgR8mR44J#$@z6MrQrHV# z?^H-^RT>V2fsRz{*F>yI!QSpjPD7r$vbx|lW)?la5KgW0`0w8@;?)Lo+XJ3|U#@rs zM@P1+@8w6sL5|*1Mqik@Jc^~Sib-eMP;h+OIu;C6y{2V0!0rsC6g%8&mXS6Ksd)( zXMkSYjk0BawskCYl_$BQmi9<2Vc15^O-A$f^xW)4%q}SfeWD8~`VI6`wD~7zn=bu* z7q7wX+ekxIR{6uck}>sJ;qZL|*sl_S>}gU%{pQB=ef`L~JE! z;R#RU=!ILc2|DW)7jsvy+cXfZT*GwOzeP)|DV@b1G*oSWX`+p4h_l-ISZrgG3nlEw z(!eNG+`FeKX>)+1-j2DRoRTBQhV;a*2oR*+EzU#V+NnYd>cKi2uOntHA3+)L9i2!K zs6W6S1gPoH5HTS1ym|8#2)Bg|ii}zkIp%j1CfnSy5>E}4vPu5v5I}9zQp!d zIAdlki==$Yr?@uGC~^shC%0xznQprXnv&FCV!mNJD&JiUsxqsWZXTgKrbvp;VP4* zn1N`>KS`Jqcd^Ot6o{OfO&c|mUtA!f{ZVExhK?i4J$JhCn$Qt>ey@E2&GLAKtAP1RVCvo7pw@b!oeGUh|YAD5H>)%znjSOZL< z0o=153U5*plKtIX*W+m!$=r$6=kgABtmS5vr~CS+*CUzM%-2f*{YVE}4R~ikrraq}_K~y}=7mX4$%$ioSmb)mXBMf95iHFHq+A?A z-keU|-Pvv>g881!L^cjXL+taKyPZBE(x8B%3cAn3%gBfjWPujw`P-&hU?74t$mT~K zlu<_6jqQ%n{VQpyR~y&ANkCyWR#1Qj!8epr*<`F|Gv|8wKi|sKr`?Cd^KSXtC4R^T zYG&nga~Ch2N&G!BJ0W`3geRC7Afv~<5$uYi_@x~+Nb50JXRCZNgk!ux5<)9s3Tds8>{ zMpN|^gE=D^#>VSCG6F2PqM$5a?mOe@WmE{U(lM8N53(8aT)CIVi%e!CvEer~B#?WZT=kMCR7&k0K1IidpWd_P+qw_tCTvQ-Ff3 zG#W4-N;P{!I5sv063YHT;7|t$P~xy(>OBQnrxe&xg*16K2Xo$HWs@E^PI^dM%-!Uc z?gM<;$}L_7yJ;cbpMtNiuE$23$+N_Rv{#O}fp&6mZ~!3vp%fyzMU!L?#-?+J?};rM zk2t-@39ZOA+yar|gZ^A6?1$4DC7R#x4|`Ri{a|u{7niAEA;Irb5fpKfWb`a(uOF&G zM8hiv;W0(2{G$2M*=1|=W*26itQ>c=y4?;7F)txi4XhKsJWsCTse*^`_`LP=MYIE_MabnR2|7{?Xba8!&}`?d$(*~puOGY&C*S&H(9H3=9p)$jH7oJtnIbHMZR4tvsaUtIiwzeVTPubFXfI#je$|8JhRpP)t;fk8ip# zz_7_%bF{?WW15a`KKlE&${DLS`j?*9LE%CHb2tPUmkw!&&ZCNTBDTje>~tfcsF`qO z2nV9&Oe;TFX;Tk~6pZN}{ zJ5jgnWyBqz;9wymkL+Kh+H?7pDc*h!kCu2@JnOxxS>G74xFdFmP0{3|_gDSb27(n? zfqGk=6X(-Q6KX(+hCsHpqjNw}bU0rZfqi<~<~wOI@u9`@qSH^7MXg}c!gSFKk9?Ie zS%h38OAAwH(R1yaL~mYMorUsXw#(fr^1I8E*cAeLVTIn%%5eebqBFO=%Vpm9zvB6n~;NzN3h+ea>MzejRbkq;M>D+ zl8mg0<@0pNou75ubee&nx+)d$2kCwGC}=-PLK$*{OpT1_E?K^Q{bUp`S3or}x%=K( z)e?m|-~-8>0RctA_sLoswV)ins_l;Y6a5n1`J>H@bJd|u)#&^8y~S%VI%R*h+Ht?`h25p80u<_2^RRP)!E&K=yc)16d!Pwnzb@xM(W?pk{cVKpAzI|@T-VqQ%i8i$pb7{(HWS85LH z8smp+8ofJ^3%Vueuz?_zU&2R>u3Q+mR4Xc* zgNE#USMteX09?aoxK)ZxiX2cOC6QTIJszNTtCg8_&sg zf4BLp06y(ospF|-?{D#f&{QQkFn}hWRVO()d9GZ{zrC#GN6^b@uOvdZS$z|VH`cXN zbK&-v`G1^Z8Jh7@ZkNVH?9XDkFFcnIW+vZfPn`2f%b8*x0l!HKpkw+p#KQQ z@i_9QX@=%1@&k8HLWp-GF7EE;*2%wX-AWeQPVXYh4PZND+&jp8ZHVHl`3P6YO&lPu zLq+XlPyu*4yZ~R@(_?bJ!vk5_3-1Dk1{fdin3s){R>2W+n5grC0o4b#XkG*CV9LRX zx=>A7q-xhiIaMUg2r_}iL$Q$Z)# z;3>!9tWvMzkvHwlZ z%!$x&x7eky`W~}(ecvEOqbV#lwi2-2m2b)p`#hTSQfuP!1yRQuFH}N8F6S)jd#$c| zqPd(y&A;>+C#T;^YKhC~H~nd$u39!a%`usyk=BE0zasL{{?lu(@1ZM&ZIzTxbP{a7 z#UyPo=tC=9FoM$lLujI5ng#iS$@Dnt)Fcdri#3{7AQAu69H9<|J}}3PiAfZy-g}&1 z2hJarUM@EY_=rd>&~PyIWtymcPhFt2kQva`Yq+h&MjSV=veedI09G9^%U7ccw7io) zYV^GP@RqJeK&52r_7H*cbWu{?QgXHO!^>m-X8j)7sy|Cd%auwoOfR~*x|C+ZN%`o; z0CMP3Tko~fN4g%(Y%NbH>jVMySBYTUp(q*|+$e@wcP6jyZ=b3H1!ni99V?DU+FqQ# zM2fv|$>2mKQOzay8>xsSKqUn}ih+=oE25dV&2=fDB!If2r=Pr{3P3J{exCihoH4-~ zz?2)T&gZf&zu-6N%@K&Px2o4SuYWDlkCIA$cq#HL60)C*(jY;*~}7one26< zoi$2{akL{;T9;7+4G$hv%vCAyL#Nc!%q8>94~(pbV}TGu>Xx26i1Tm|2oi+L99#}E z7`~Apo-vY+E7GVl<$j|by%2bOJeyG=0jmEo#z-&jHkK}*Oo4~-vGnRRmbqiKm@JXxPz*ixB0xXD zSlQP3dZ(t%-4iiG^MR5QR!(`&(RG)ieIJLa+`Mc$#hcP$m9w-|;`P=d?|A)9f+ELX zx7QChGH<0vWIFTn)^D%D`oerjq4CH{{ciQcC{K7b{D?SJR5xmG;7lQccfP}o`qQ^d z);|CJYA7z6zH}}8Xh;?0BEKB_N8r3*R}?gNhuQ+YNv=1E0@eN?~< zFOTecnKsDhC!xQ;x|4G*_|iR1a@DP*6Q|_-^nA63Sf$F46s7H*rfm^E4_G3qUp_)) z^?G{s=?(@^+givVkguXXCR&X}`GNz2ac#J$i~uMB1_FWxE*Y?I0k^@259o%^e1#yo zfWX5Qv{seX)}^|N^2zv_d{(G3RRHCm9*`<{Wx`#cwp)^!7H~J=*+^w4o}2o2Mrc6q z?Y56inoliUg1vF(ShLfRag{6RwiFZ;06pKWKu?cJ*2L@f?d6}(%_WYFSgOPaI^?ro zKRJ+i9OsGDku}SsBnju}e6%qM`NL($p3jULEoOKze?j2xKaET2tK#0ebPp$ixhbaO ztNuF3wBM*wg7BS$eo(Ba=C7_PhBM&XQkH|crzeeb!lyP7KRwn*9D#LdffrUfiqI@j zla$Oio>|wNGljj8S&%_J_M{ zS(VnN`L!x>FZC?AYXreFBIkqq=U9l$_e4`tB3pONf=*7fhMLv&6l2zRL%PJtH_*Qr z$WF>~Kj`t*#rJda^4P$@MKIu&t?A?sSpHvQPRLuUx#uPyz=~rXMEVE)$RY*NYEaAq zA7qN4Yh@NgB?}np48+tt5FiF!ZemX355U(3W;uc(4b(I=0Bi%~EHLGVVZcsTcPW&J z6O1IWv$F%3q9wQe*S!fAOv41B* zEJAq!=H!;2J)4iXYlqz%@P+mxDKL~v%=QDUN0?MLgL)LLY;4^?rFNb?nWU>|L1FL1 z;bP+znBocC6`&+udnRJo11T2F?*QsNwi1HC1(E~K`sOgS(=hiw@Z%-t9hsRrc}HTdK0?t zS@%1H&|E&n))22Kz_9;T4jKb*)NN5mnmE+wO=MIkZ&l24ON+_1H zAoauqF!um%7$~l8z@2Zc1dIaQ-`gW5B<$q_Lrfn4{{|NiZ#YeW=SweklnH>9&x4yG zfh55CCkcB36SFPQV!*Id0Ah;CXpnR5Hl48H!)f5z;m_Py|0m=rm_{hQyBtD=+}9_^ zTkj>K8$MfQ-tj6e4=oQ7M=LBM;t7mYeV#VOwLhMR1tCr05xyK-cC*+oU4AUAbCekB z>sZeYLPiE(+q8*ggzQl9fpx3X-22NZx6jw-Zz=8MOf}`#{?HtE+$?vR|E6hbHbwCdAuJ4uf5TSmhA0G+5+RtX70FQl*~=$jjscApwNeO+lKstobsTA|A_R!di-5WY9Bn~Ag5iL)!9Yz-4Sa?_AD>5X zGpiPV!k0X_?A>1RcF$6!?JOX8tjnS=^fC`Xpxe|5_DBk07lm~n-D_ukr3 zi(o_@%<#pMAWR*4xVbKfG?galNa*07(b_+gKHZ@2t*2J{n9OJf9dT#hbuPxJU2Kw` zE`s1P+LF zgLF%Wq_jx4l$5k|H%R9p1f-;GoM(3hj+rjK?@Ww9Vvl- zovXpGlm6#k$yA~X(O+fkV(>#5ttaF&ms$7x+W(Xw^^&s$4;cAC#$4iUaeo{u%+XshXe^57vh)Wrq3Zn_L6kt1@%Mno;AbM z!_zYS_oV*99Y&WL868ztRpmSkN`4N~94tjbr`99cF>>x%4cQLQudd$KS_}f>{PAiV z1_ZF?{cbNn+OOB=mgi7{Q=<^!^1t3c$rWa1%6h!>6PKV?cMnrS1E? zAcu;EfnmGwEl(z&c~cKbc4pu0`1qJ$VNoK>0HC&@1t>1I(tlQ5phi4zz0)SkaU%Lb zn=Yv|zxB1PmJs8-OYSKFECwfo+;x9qFe(4zoI!;Y43v$*1VF;=)1@GD}31W_6>K``p<^Utd2xJsmLidQaoX z1A+2#Hh7<*Z)A?XI*}c%^JLZ_?}3_Za4`-BF@RL$yb5|)i;Rs0?NCE)ZP}kRKES{( zpN&FPkrvSeKC_YW@t&TZ)qjvCVroFDDPuHLWR{nkMoJyu(eVUW+N@p`)8fao4MV=n z9|HMz(9y6bW^XvB zK-mg7%s4rN>qD#q@WIChYU?{77R;kEd`T zZlr$ApF7FTWYvCmQ*021EgCB3Vu5s=oTTd{l_$NEgzRi~d?&QHv&ByH8VgHH0$6(O z3xL)ABWjUD0^PCxq+=fU1d?6=mSHEvl<9lV1CdnshF4Ps2qu>~7tSi}HHU)$`BzjW zU0#JoXac7ZXhR*Ao75AE@utea#2Cp#C+vzb6wq5&n_U_C`T0df{lQ^}MfU3A&mSi@ zw=7;Om1shCkkdQ|?DSAj!oe^+41-9JpC2UXW(#|{?2e>IEPy`-DhqwKRNxE)%!q(v z@d@|R8UBkH)&n~xE^~J99a0m9SzB0N{>`6vkZEmQQ2x-6();zj+ZEXqtreh;Rrm)>lZ|*_0;!8^6Bj?*FR_RF}8rJwS)JYjio2us%_qb-U%JUA6}oLUg^{2 zvIq#KIJ_h^C;Hbk$=?bCkx1C4h7>>6;N#7x7a^!mNCvxeI^%2B-$#PIrFqj zJ%vk|lc&H>2iiSN z1%S40fjN-0jLg3TWl)fjAprqTKt=>g5jJkIYVI)%)-M2bSFLq*u1-$hK<`ZS)^}rj zTWbSW6BX!O^{Fs=p3eUlsl|kC_{HC=({JP4tXCo|v;gaA9CJh!xa7^7C>WNlYG+Si z6@M|-{FMpZEJg+fNK>OgRH~JP8$=>0@^R-}=&$K+VQozMRQ5P1Y_HB5Svs2LF zQ!P$+bfXP*`dMtPJ`yOeB})0-YHM*3lbvrRBgXc;QfIEtYW0&u1z|G1_g|S`F<7t7 z6I}o)%-bhdol^(gG0cLs=b#l4)CiI%em?z`VTLCXCbZOnbLd7WL2E=`&XFPFND&1b z&w+-M6|{EI8l=yk*8)PqzY4rJAu%IO@Eddl*iSY@Oj3Fv&LZQbwaXeADdtDuP6qCu z;IDz`9=s>c2rXbh2Oc6jt=ZXg2<>y~X0KFE!iU7H)Y&5ISWj8^4!^t9$`!wqBe~Kn zD+Q77=k`V751n1HLjFI~(-jO(3ob!yLXLpzM~&Nq@{pC471ybxtAH~NlXpeBTd#sN z{ntk%t)_ii@6JnFrt;NG-Gq+ho=`uz1ecR?>=h8n;L1a`iQ&Y>(lTTvVl`nR&I{6D3-zOEF?7+ zRG-udSFf}FSMWmzl8!qBy+B()k09@>Mv#{aqbCFeivVXrA8<*1nzj{yg$29{^+{!N zBf0!y@hLl@(2LLY!-_G*fZp;Z>pr-Z7)k z54dfNX=Y*@^Brtop)@$?^k|yhTazyd=%SnJqBqVs+46|~G0e8Z;mB9L|6UmQ?d|v= zRM8)8>0UQkMUhOq;m$?NUX`(}TP<;5I`l#d5-OJn7g|Cah#Ct2=^q8;AFoRQ9#h;A z(x}^cXZ)=!vx8T=FePfJu2b{Il+R}7Js|v8jpu+=k;MSNBR?F;$Lt}$^&A^$77Qz| zs%kApziAgj+s^w#5ipDw8K(VMQ9k|C%|0Ct?`0Czd)sHWujwy((eR8(Bo+W$MPRdQ zq@Fwn)DOo~NDznnN6kGdGG?SF?lpd$%C~MV3E(T+KPh(LSn`vp{Sv~?f&YVw(s!96ge9-G*$x((PX3`pmddCQ z_)jl3wKv}=FC%|Cr@lnwg0vA_VfmCy)CyPU4Wh>|!nJ zml3=ec|3*x+yuelCfe;#NTL1_A0)+d8N zI-4~3655BEt)ff)jTj29yQhEu>ev=&mrCh7mu&rJHJ$l=KLKS+aCFz+BS9|UGJjNd8-c`);>OW z8*jo7F1_jJFZ#pVwyKTYs?>{@8ar$-=dS;(21P`W=) zyp>YdG6FJB< z&r{O-Roice@8fM(UflAidEtbn?VQ&?`IE92v)j%yUHxHM;#9Ht1EqZ=&g-Z_1Hy`U zCX2Z@;fW=b4x-J5D|zT&x3lK;+C&(s z8v;lD$KuT#$`{%|94BN%1frl4nqBUQEaYGO5CI!{I#(362Np@m0np0(`ugSsJbDR` zF}d=tccS%CRsH&uH&{h^r`Xab$TLHxb^DDBbw`s|3_B+>L&3&OK+bVuB3`ORN72^t0Sm$ zZPKt5YFLMU7NS*?4=JeOj!x_*wak*SGzgW{sM2XPP*X3Q0?5H}9A96gfzD0!BJy~i zBgR#L{R4toCo?q?HQZ;iKzLcpX)+S{TtT$}l0fo?#81u8l3l#I?U#-#Er9zZ?7aCC zOXLL!2?QeFfB)?=SL{i22bQ1Ce-?CBl>&2s#dyQzjc6{#-#6gn&6L3|A{HF7A|ZO- zkcC=HjQ@DiR}D5ukkZ!IkFA?nERw^M)l!Xz{Zc2EGbt8rx9{I+a5YypU177sb`aSoS8uSUA zdj#l$r?%LB)mfJ@he=V4;|p{3ucoIDVBkyOIO?NDi-Y z0Lmg=D#d9UxTg#E$xt9qUq)tEu(?Vm9~kWGxBE6P+U4+AD)g3+L%t+~lLd5q2Ctfj zwVsvM?fEGBs|*fQzZKfNWDenn!CrH&ccv>G-t}iZ?ruX3C=LXD!A;RMjvH6n8T2%O z3`jISJT$1BQJBEpsj-^c!eKbJxZgKxT|pfL|)t@iTzebw@?djif6bi zmH8coAREXJ3lz6lEkvt(mWhW-tMM+u#Q-|1-8_itcV)PnL6N=-udA0}GnaoU_!12s zGM48}_%dDL+nEJb-~+LRKYa7spkZW0>JkbmQIt8U0TZOGAX=Qw)WGjSFBR53sJ{Pu z!7j#!K0wswbFn9Zs?LO;;uG#N27+?M|E(6I)WvBl?t$$4Q}JZUNVK`uMAv5|JKcRk}AOK%BS}MMTi-TVB!3+AjVG!-@v`P zan2T@M<5^d?Q(B7u`H@e5s~oiSW5-Gty0NTH(DFF%*!7a1g7$`By(NG=kKVv z8BL`q9k`nfjpdDJ)yQJyn#B`Fna3XQuRDqr$T@Dshu4em=F5mm(?Zkk8`?#Qoz~@g zLaCi{f-bxguITxV#Ua5$;xlfjl!y>hV&utcI4kj)Kt3mt9uAM(eXmuib9Fd> z@{uxrq%BTM;IpQw*VdLYtz|y4=iX|2(2Hgk`(C8Nxx~8j>)ewMD-&OgeIH&y1&Xr} zXg&bs4FEq1g)TsAys@zXNoeue8mwf+{g_JkmgnXB9;V(jrs0II%8xjRad3vTZe;XM4{n5J8&t_*FYcX?fl#o_Fc2~S83BMM1o5%S(Cq4Xr<4{0VV=UB zt!k4Zy95NaJ~-1~o0Vw&Q|>msQ6wQ5y&p~TzpbOH8B9hVF?I+TI!TpZ%ralf-^g-x zTh_2LBr2*3|A^HpK+?5SzB_KLc%I3~rY7QVS{Z))Y$uCX-`JRF$Aq2JZCJQ~Q53H!Nus9a4vd>F<*8(U{hs0>!ac zuA{qP86F?#F4aHA#h63yNFNc7-DJ2QKwp>}G9bSZSn|A#uxuj~hHT-fGF@B$*1A>25EG zPNKsN&j!!Kab`|n5|cAhLq)g!Q7DB_#LcqpZy7P<8x4^2wW`!b2maOQr1E0k_@Pk6$c~v4&%8w5yVKRF>uFU~%A;T|F3emgP zo)sxwuNP~i75n9v?Dq(&^;Nsq^27fWP-GQkHVtxS@oM3B`uKU;uuS__s|u+U4Q%I* z<(wKf*RmzW9)wxV@Y($-Vd4V9e3$JqLAi8MI2@K}gPlq^Pi9EqE6f95M4D&3WU!k- zqG*G`fq`Xuqos!s0MvtdD!3xoE*(LrqiEZRU+}5*nTwe@b&k zaCq7^K9x^H5v_hF&asZ6_0bnr&FemGxJ6&h#_HYr1`P2_&a1uB^B~Nk355oe^2h+g z(u506iQvHUcT{M0AYAsuk)%Y1;9$TduvLQ3*1Qagf-B7pQa$jc_a7NyaF$hg z%oR}2CaaE)E^}AWnZiLR!jg6=`L@wdy_$eKveN#)WqcDJo#95%KP`%%s*gecuvP;_ zf%yXFExSRzY0P46;$z173&_l|V9B8(D?b6}Y;usRDS1WV*re<0oFOLEvuWQ`bKi)7 z#fwc_L5x1;t{2Qt6B`vP@aj!JJVLqP?VJfP?aq>O86upcZ2PdZqsq|`AKXh!PvcAF z^$SHw&D8q8!KmVT^?-*OrAARa zbDh`B<`j^WE7Sl1>qAotyC20#@K8;@nJ;y1S>xtCItmNP;h>f$D?^oj>N)c`?+0a5 znZajMJ#u}wegZ_wpHi=t<>i5@J(?*BghISu%M01N#F1EN-0n?`vG9BUVabZnRAP{% zO^ZvxdtZOp^H?-vH($MtugE8&ql#2Sx^N6b9x0sYD96&BKnA66U;9xy&L}ukG*;#^ z#s?o_6VbwQXo<8J{dTJ3maoU0=*_*h=EuIjKRBgw*!9?1o(Cg-MsS%E-@P*xK_eF@ zL&V+c;zvrRfh5Kn{{@?NnN>^k-$?@|okli&yihwJAq6x;7lOPIf=@BqK7Sc2jan7+ zaEe4HSzoaf)c)Maq77Aai9fmXdX+EyT|XZAh(RzLyHdw<`_Bdet4@W@(GNj={kYoyh)g|`JBkyxJ&^@b?C$i0Js@|oG=)m|eBukX^L$~IN1Mf! zUXLF%=irY{#OezkP6^4_TXeYtmez@e>;7c+$Yyv6Wt*G!JFPb%9Z@`S+}$oazxdRc zZKM@xU>F1Un0Ea^aC>yrzHCy$NGx~|2odL$uLLMMRYe)_(cB(q+k=Ys;>_-?EA!4; zJXh$6h@1_rCU;KI(w+y?ei`UTw}RyClS&!X4T|#clx^5uIN}v)9j+N1bn=h@LP#vIr}+ zwEVs&+M@%k?9D~rpz$u*1;bc+AOS?}4Nr)M0S?sd#p3O+A-rAqH1Ubg;a_DhqqJBf zmv;|HOUWBtB*$z9e5opm0}=KxaYW%_#*<|$fASzP(7ECP!DAtBt#L83Ms~FbRH;zo zpRV7#?NNi9rSx9m@rNZx{I>m*>1^B^#;G^JnBQB}q~+_F*Aj{J=ljc^rXTfCgSYPS zpVpp->7XmvFMM0IY4{ixrkpFfGCxlQiAs$B{lWfo|8dOw#nQ`#*8;G;Lax0K0YR4r#b_HyoH zH@?T5Q=-(k3nD~Lu);7QBa*7DB@EgD!CbG%Y5OFln&%Z#b$DKMqDd*qjyC6z5 z&Cz<0qz`fRp?2M2({nzV5lQZa72nOoz0``M;bt&rE1+EYusyz$_2%4Rob1qpNIIUH z31r6C0be|`7?3?|4bq(2D64x~?jGd74wFoMv%H#b-%N&=A*xKW%%TfbvBVetyL$V( zd+PR+M0D;+JnrT^k3G&vd zG7*)D^~y~Oa(Lo)E^ll~6Lb(iW4P!@_Mw;xVUdg5LbjwLK0}7oAo>P_%jhrMEo=1t zu{J=25NT}RlAjt6Og)=E(AC7ifF+6+n9EqC(`yM;{NbMSS*wqZCi10?))gm759Wfe&{)a|lV@jVsYi`v5I>XE zrU3-RR0si6Jg9R5#T*t`g)2@#)*3T1D#>GP7PI1T1>&JFAf&M}w{OA71O(myEf)u8 zIgJ)fUa?REi=1EWR{s&-vJB2L#`I!-tyrg8RjoV})_+k(hG)=xN{~;>5Y-dFAt&-( zQ7z&71MC)Y4n7d1N~EyrMtvnFBU@_qbj&RLDaKXu;$b_WeD#lDn>!V`M#nhu7*l)b zrGm}SpW6d59Y?VN{vR*DYMw7}Rm%}{^DPsx`sykU&CVv161J92s4`C5=Q_we!Ym>+ zf_&>s505wt|#FV>Q&h+)lbb;1FktuCA!@@r4z1iWCL#^50p zkNxkN85swsAMnw`W+3D=q1!D*lkleVbgy(fm~&r!_|zN5!+~>u_*nP$!CQ}J-D+z|WV!H@oWA>vcKXSX%>-Go zTdKKkMPCVP91bn2{S%|(WKnVje6b39%rV8~hZ80y*Q;UHla!JO1GqrT*A~90H?|Up zY7oS~K_%(yYhWf%3>g3i`L24QB+y8Js8ir32Obc%G6Z@v9GFp_+VXd3N^_tM2UcxM zV(BZ50-Kv>0Y|qmw{IQ(2MZ=Ku1t+sPGb-=TeB&uwKyoI4c`$!gUDjk#XkUtcCabH zo$@Cg9bi*wXlimv25^cW@>Bhf3y^I&sBnpf)f&)k#KyEhU!j{gc{l$sh$nX4+-V+A zd*a85dBP-LWefBKYbnVjn3H6Tp8D@6WM{G#Qj!nrTYt_j@wQ*nQ$UoEM-8_~U&Z|W zbpIQmcLe;LHkU*eY=Oa4T?k(ws8pCmQ6<{+|4xfHr8wFIPc24OfC&MN4YRVyi>Iv{ zm$>`d+uMVwLFiG60um%yLjnf~TO`KVW{J10IMWTIX3{pa6vo2KJtAUa$!FSK4{uYJ z=dyUCBF#^VVCTG=?(M(EdPH@t@8L}Ue;6=(c)8Ud?>O^Ky>xbyjP!CGR-LnYh6Hg- zZ)RiqzF!E|+M+PZPV&^Xt5IBR*%q>i0tTSPOAZ^t!#wFT_ z)6akNLs^RYYNPQ&s6>P0y|zohUshL>85TI6)$m~VovAWTsWG-BozB2v@J9PIxzXAs zDFHGC)JQQgF#z3;?xm%V1AlR_mhdqFq2px5(j+9M$?}ufF8(1IMgpva1SLt-$g$p*^d+H)(&UFQ4sR zg9@32#&4F65l@1zua);}shj$KRJH9lltb^R)!&746H8X-CMpc?ou5gxnb}cy z9)}J6S$NV4kkQx_N-q%l^jZ}7VH$pjS}uOveJmWx%}DbUq4?Yiqinv8gX1yh#UDMb zr|Ufmha|=X@I>N7GIQz-jXpUm3t{QQLjXM}*Y_-P{t%EYXRlAU1fW^ms->1!_l#}W zhH^bcM~v*-F~((Yn6|QT?gxuHJgJngCd*dI=JUZF)K)_`CK?e<{)V8Pbvl^?!&dHh znfa^p$d^l-RGNP&Sv8pDVeh)C!tf9tL{QBzAuPq%)RnXOVh`VIjCat(RXK}uRjN5K2{B^sqaW{wFu(hOVXm246^ zTPFD9amvnyS^ShOyZljTE*-qAyPkQ4&FREK8RCC;UEd5!R9qk3$xg>V5s~B0`E55s zOdHcUjGDfE`9jUlfBi|8awChE<$2iI`fJzezrSCw%y@ST`@MgePuoY-oJdd8uwDE_ zc%L9n;^Qx8SZeo&6sjv(=&xHOZ@fF7u#ke^M2mWK&-v8jZZ(Re(k4SZ&$(NJGCUPr z+tPwa&d(Wda1<8Pto9A}2LxXH8WNEK=T89#Y0{!$lC89;O2Zfh7N5(@%iz1t%E|)3 zSoM4~w@#@RXe<(&S(unghK|!FRcq_ZYG$Z|8US;$e6~!BB^;ZgOs5broN`Yg;kC0~C5ESZv(Hy8%-bnjU9^)+0mX-I zT<46B-8Y()_SxUI6W~k*a<{nbl!4;{kS|Dh-^rajMM!$Nt@MYtrx*X7ow@Bu3&{}e z6nJw@>nR~GcO>-b<`+?i^BBtac(SG99k1-o>JKA3nptUbZNL0tl7!}y{XtnA;&kS` z;dUQxH-fw;J$w!Qu!1}(8sq#z7sDhg3T?DR*ya-N1G6b4*IVt07j+MtTAr0dkv08r zThh#;aj6g+1GHY?dpPpIlLVug?w%fcS8Z`|@!sQ@njzzAi(@H=j!yF!bp;}JgKdx2 zrFv^ukTeX$&KAHfl`~zzcjGw^Kqft3 zuB#dcopmZ0>Y8R203#m`jaMw~Z~E^JqLR@=ArLD}s5!ITueL}1>dd*ele}B|J{}hT z@9&)@CE=lV3*XEDvF^efF|3yV^18j3lPmsp?bdq9s;W1IP62ks2l0ygDEKb<-LEjB zhhW?TzkoLS@k>qA?So>h+H)IZcADFP!ED$pqI<6Z1U`6jqb@aUEmtJfMjO2;;O^Ug z&mlS@x0l^{FX+eNo9fmtc-5NFen5yj8%2p3#jo|Ky+J!}B&N}g&C*-`+rtOY#@@Yq z=iuOAZCyH}+66fEV7?2s6VSpER4(KtvLzv)c)~U6o61X+0x)q6_|*gD9nc;cx44n; z*=T{hL;ruzBM?htLV)|lKWY>(M(_s`Juo2z@+LHhO0H;|D{Kt#VBcEKPe&a-Ru!C; z&el(FXZc9~oh!}+=_#47BfPDB-wqLXeRjp}grkWcuC=swOf$xewO+9QsS8Q?W~C}A z87!Gc{9LTbul26Yq4iz1&)B1#aw{JQuYGx~A%jNScy?5IR>Q-f z+_91Q+=b9Tcl)n~ST@&TjrX&9%#AF?9eBRqJsk#RS^KfxNw|M_Mne(*>`LqwFaJO# zzX^o+9tQ0Tppv0UJ)>T%rVb^Bg78>C9|I3|_?v@*FFNIK zBqa;XJHZsSQpd2yF@;NFG$6l#?nkSbX5^tj*Am;e0*p!UM!@d~m@+Yd)C(eqLFf$* zIr%;Kk`>sWfX@UmCP0lAK(`DC+abtUFJL}EHusN0k+Mt$%K2d;EuK{T@3|mM zz-0S{FIO|uO}*&Cg!7qX!)koZOUY0SF`Zx>$d8MgYO7Ijty=pELn%vvhsafaui9+e zKpgVb#ja*w7V}m}Lkh~^f>3{kbXJn{XinOx1>)2ZgvQ_0<%1TNGwoY**L7zTof&T2->vSam;1I1`#raqvN|an*9q)RNo&N0*LZu0l zJUtuc90ysNzyp{eX+J++G_mEeb;V)7RaW$&n!HvN z;W&Gj*=60Rez1mRgTab}=Z>yL7M{|o;obP^R=QxrW?TPKf0*^z**Th|?kRCFF;N5h z8vbD(=iiQ6b=~yHtSffQ4xX{MWvg1mP$GZrllKKe*nN69h-1zDTQz!Y&Hp_ft;Q{`@~14> zD*qZ1eEb5Pa=;M^3nR!!aJ-T?BGQ-*0CgkVpH_Ff`+9TM^$sc3ZO?YD!g}J11SsF; z=9}GN7;k+~r4^VthH2rTN_lF;m>&xYUdXGsj2Uz2g6QVnS7~rGQp^oYN6AyImo^Ej zGW%Z}myR0moFEW>l(BT3eDBL1DvT)m(M=`j<_RZrO;j>XD1WikgvAT{`zzSuXK}l7 zv&qpMIc33i^BtDzc{~ad0f%nh^Z>u7weTby2uwUV6emyR=`<*|H5q?f{xE6jh)}v_ z^WZ9KWWCty>h5QXP#gxL*kqml;lg@WFzv>{GG=n5LD=|Xh1fh}+sQlZkTL#>E+wkx zM&|4-e(kJd#5iBjyG2cM?}r2ae$@ax2}~O*uBOUWbI%R4gG>36&-^;_IH9;Q9GEa53&R|CECTz7d`B6hXG@n;Vcs9m8FymEoxA zbvv3J_X3Yq<$z-sTLo8vFAyXa3IUEXptL}~01Ow{iSuTT#**?SmLVZYd|NsKyeE*k zdjb5%rPUE3p=##l=3oYkB+>L0C7Qcv@;y-4I8N%Xh=L?pz&X#)&v(2E%7X5+ga*W0 z9=t5mEygT+`}%w0XqNiq!^tzp)}z8l8eHR#{$*-+oQB^)6f`tOHkQ&@NbsyPlNG5@ zvhWHPL#ve48z%9|omLVa4!+IgB%Rj^u>ZkkVd+?Y8$RuS|Js;2!3z1i*UjV@IrW~o ztUGgJbex^a-OOkfa<;QZ8WN2+9i)RD7aMKAVZ7jT+P&SX-&7BiBhJzJ+`>ooJW}j+ zPi2?~V?u83iAO82;cNKI@l^0$)WQ!EmK)N8N#0ovN6h$UK~CfosVOgHjqJn7Y>!O? zAwK?0N%g@foq)iiDVNqw*=n;Kg#<4T4>)0+ow=bgIM0cRfnFbo94#!i+nlOTz1u*C z0gR5Xf;$CWca<(J=8j%BBZz}*v$wZ55Fr7fw}eE{=)3a|!oZZ=7-*vn3=G`dE`U0A z#>O37Z9p{pKfX2~D}j4nXlN)J9z*A>2#yy2+3{StgkVEP5<*H}U6#U_SHKM?W&G9t zMz+xRGS(<998`$f0lidBK!2t+BesoiXuGQ8^j-+Sb6Tg1#}C|o73X-faBx)Bcm8G@ z>qV!>6UlPL>?C0wl}8wZ8xovQcybvdfgx^*VHb&BKE`{||5bnX$_M=5w3dkZ<&hd{ z4A0qK>`)oh-_f@&+5F*CKK9Kl=64+{RJ@a`bw7T+JDrY==qr~N0sGj;g2>ij-NcUK zk(9u(jz0dI&sV#!gy1;@r>U;%2j+-krvozLaw7+i^2a|lfejEy7JRp5RmGC5@?F^~ zDcJFzKhcexadkL$SXo$xz%w?MDp;v#Pl^B!FZt#TeRK*nD)13N58E`^yVtLQf2$m} zNHKcptL<3VNgK-52k4q9nVENhINba5Cq4neKerkd7KKtRY%0-vK*0Qaey*sj?6(m{ z#1A_?JylF)^Ew}W4R$k7H7&LK`7}S%!3sUE9qMWnTggh%ovJmP!BD-j%)*m67#2rU ze?f75yY_aMnXgGX_ccNfnWJ8Z!})G569MQaLG#%|OefVT#bm1p%vvQ;=|bVOE6)>u ziCYl;>I?X`c;M6+f#u^Y#W>VtQQo#WsiA^awZ~wCar#M+XIaHvn_I+b>-hIohw7OI zh={OwX`aF(OlG*}P+!q3ALX8-B zAhO_4O^N%0N&|$cnVGhAi#$9$z|uKeg%M^{J}V+z+OiJVBdXIVd(1$*Y z|H-&STk@c~oV8ued8Ji|PrQW+2g8KeNtZ^7ja{_#wp?A>Pd@a5P{OA_JqDr9fM8GQ z`$s~7xlaxc=j+TZf0PUOfiSY7zGjvpU=p>H_YEAMiC!&o61K8(@LXpuJ_|=WsCG$p z)qg!1d?wE?TEv_ULs^^i*PV(WYfNjaz5mcXDf#K^M+P$mU$eKqa7K^gcRfdxIp}eLgZH8x2Q%|0 z!C(bZyre;3airc%w^zupFfcHa>>ln~HN9Vu%POoL!wuqH_t}{>=zEO|qwiEAU#;27 zDT`|IoWa;ux&>m$=9-o33{u`bHpJQpQ)xD=Hd-wi@NV-4h+=*oCtVa&YU z5zabe9z!8I@n1Zy`M4LGG(0oQo*k;Wp_oJ)055T;n#Oi7%FH}mrLozS9UF2&_c4$s zjOFbq?4_pk%+MzU$QP|Qd--ZsG&pbngBg%GX0#K-wH1(3laoIHyaVUL+Yf}T0bEas zVcJr#a_#cyi$$4)GOk|YgXC>9ZLwjq&B2#0g)hTWd-;^21l57#@6&hYW`EzMk;_r&i*7-ym%okK8qGNNeKGe>X`zg#L zb+s5~kR(?*ga&et!J&cxPCg-?_D4S6)(J~Yo%nq`kpfpK9i5_4c|U}Sw)TiLc~*Ex z!Y%S=q99%({y>dqG(9vfJbM}NT5{zXwM~OFOe|4wtjE-e)+=_v+h`{xHC3UV7UYot ze}3z|T7|;0A3_7!bCy+cr1i+gT3p5toR&85v|I399mk@lKAZBAe^`@{ulHt>d1APs zVBRyA{`P6cpGD&)`MVb8fL#j^_SyCB{6 z=USv&ej*T-Fz7^ zfc4V|R){MHj*&%8$LVBz^67OB`>%$W!Wi6Ofns8ex$f<^I>Kz;UsQ&3j!^tA7K?L# zD=*73QwX?N068~-bPT^0(`ns4Qt`7rEQxF@HUceD2Jb=?nb0w2#&|ib$6wk@&qhqz z=2>goujYN~eWq(`yI8x1iurX*%9)J`5!VcKg<#}#$*Eh{cF>_nH^ZfmaLUjJ|7(#$ zwc6hGV$um3Ul(6{CaOd~RnC1FFz!5?f72(cc2A@RX`qyRdZsiUTqS?=PEG}NNNZQp z>_x*Z5GM?bj3kd}L%wK~g5d<{HDY9-YHDiI=!LZmt;$x^u2ysyZ0TeOD5f#IW2=vD z=jruEntGkKn#kr_qD~2})x~aCEvMMFk-0SW^Uz_>6P5d|aj_YjBOrJH&fCh&(x^D< zv9>Ym*@eq|Md=WEF>Ii9)6 z)?2lUa_DINTfv}lJmY9uOvr}A>GpltsE>=k%7`{Pzo69J!PceW?6WU1(9q-k!BLoW zW+t$I#Vb;cFh%eKXfO}cm zqOlBkxA2O)ed5e`sE;ly$FpRAnNqrcTiu3}-O~%<=Tj;r-vvCZr9TKkB-WhQ$W@)I z_1aOPd7wW8XJ!mHW?)2u-=Fc2w{42}C4&=#?6RZpw0;(pwV21yg(lXqPwOxgZR;=f zk)$b;eZfbCbZmMLTsJe1HL`lp2jPs|?J9YEVqH+(!A+`Yn}F%yAmqU~lK#W1y$mBIY$i1L!F6D&ON3oPHY zxoY-amm!L_T(fv=y(@$S+9^Q$Gbgv%-s4Ak6H|#w{&&1x=P}kYB-RcbYSXM(<8K1_ zo$vlkw?BS(og&$k(U+O5860}LdNrC%z_7q zLUIQj&#uIv2@c$h4VMUZk(C4^0RG0dB+bBe@kM(13uF4IuLhNKHVui^B5Z6GE~;Mo zx`WHY7D4o`2w#%X;Jpr~M`cy4W}`539+UzgQd~}BIMl85=i`q3&Ez=?4EBfh*?-5D z93yFCV=H<8Bfa;NY<0GcO&Oo}x3WvaHEepf)uExmJH>J66o=quG;B8VriZ}^&ep#uD}n{8;}!ike-8JymdBeVNLIfYi3cS_rg`%%q(wsCy`+R85vnYUR+G9BT7Y_ zXvJ7&_v610>oAO)1Jz=-WyQAfv0MkOuJ4NXBeL2Mnna8@w>rZkKl}LzS_t>=p#A`F zkocsM!_UB^^)Hb7^3pPf7NQg?Mi`^|cxc5Y-fFdbM+zk&;4bxcj!K5>EHC%qSZkp& z6Naiy$6@tUGpzP-To}9O1RTz$SZLA_TW$-${CpVL=Ov_fx5?p5W1{R=WjE;_E~8o< zF~IQT7#2|l(prBt1(mqZzJ(&{6iRE}sPAt9+0 z<3T{%4l0M9o*sCU;Oa^+EjZAku&YA@mTA*1z-h}Cr|u#HI17f^4&z@?4EwHZ=x5vI z2fH4G9zD-aPLSv?NE_^y#scCf1lG3>#ekj;a2nGXQNohM{BrL51q*d%9nQK-Jp4Gz zs(#RFqgq_Xy@`JPRIbh{_rG$nS}#)ZD(RBb{2wU z1kOGP^fGB`|Mt@X6YIm)qC_HEwrdpkpz>1d)4ae})T=AsP4U|CTdGtVHcTqfA0Q#7 zetE%xFL&kqRI71R`zg;X7FpRM#-yZ*X$w8*w`hjw)zXSWP>fH>ELps#fd6l)PVJkj zu@g^sp_vr?WS6FW&kjqDCxKWVO56gkt;nWS_Xp`dZU~IJE&U1;^UDv*_m2hxdJy`^ zPLRXZW12T+xTDT`y8MpkikJwUu6&jy7Ae^+rGHDEB}Ji-M_73I{Yw+K;8^mC#OBz4 z#W7<8f*Q24VNz#3-eP~pY?&?~jhMffbQ?}`Um}Ml5r|5#vZUL)6h+}q`a0U??zp^q z7f0jN8ruhh% zr+QnoStkiKT;Q8WnSl>fY^{L*ABahTF$>KSeNbw_0lnBxYTgwsSZC`>4ge=VeNqSe z)W858LJS4{4L~QYePgSuPb@vsJ~bN;9Hxyl&{Vz+BkWIzq@q&gv7J!}GOdDNNiKTgNMsO^2 zoX5~BWK&sHL=Bl{;l&tJI`<_WrD}LS46Ikb!cOc(75NJI;g z7ofu-BzCAgiE@UFam)C`6SOtoYSoP9tABF#%MTYZ)k1HInm?dyqTpI5$AJs&az-B; z3;Z$K3CAUFN*0j?_c6~rFM8=b5Zscso1?EViH=Y+a&vQYavbUwU0hv{JcRzSiGcrb zn+X*#IV2=3(qbvUM*^jGhUs6awO8vy3ZA!rxEk13g1!&bEr6in`R+*>xTIEopKP2- zteiy3x;Yufi_A=Bd4IEBapEtUk)DHZhe~m?01d_IBX;`8EpPOaj?b)a6=&h0!O^eV zoJG|+H9_Hk+~H)wE0gDpt;lo@`~rL=z5?OHX;?1n#5A0j_fCKCqU$F1sDw(-e;8I& z4PD?#Vzev%O8g9Mh<2yD+`5$!o0x)VsQfWGHISgUMluycPN#Zvth>&E1dlU8sWdJ* zpa#K&$gv@ZLNlU*>UXPa6_UQ+Hm`#J=%a=3nU&=^JBOxQ} z*s*2KS=#Xb_XWRd)uay9=p#m1SAc^N3O?SuX3}#xuf_Gk(J-|3#&A14c7_IM(2iwY zi!R^*xBLq*IqM_d#Kfg>zbXo`-Q`8M&&fhPu?1;5)DU?o2`y`zhxM>Nk1>I*<-9B{%^j!zSApo~RW#(Q~8d?jg)yw(&;+jCR zXB2C0*Do2O^qRgfBW$4u6WQNbEs4ns#-3#}wut@Xbu4O^u>R2)hxwSSq{! zStOn7RkuJIr9VsPr=_DY0Ehsh!|-sO9$O4|OpQr(d`wKT(xG=-``Iz|AxpXtI+%YO zk)hIzdG*g-5(eC%px{VH;cln7o&6p}_ppzRWYNkt{vbP>vSN{YeveWqnhm zWb_@D(lPDv6Or%p%zkPaYaf3fD%|bCd`$d2BVFJ(@!6-G_X}UEa#vncGwOE$c?$4*4YJWtYr9a2R>eh=7u^ zYSxDJZ;F3{d&)?51lu=@Dy%VqZhpS~LsN9ZLzSMI)7_s0AU zf_BWg57h4bM!md3l^VwCv=|6MY($yHNA=Q+GgzV1BGlGUECZ9am>A5uMK*WD6s5zU zpddi70{9F+zaG;w=x}zq#WD83GK9qi%23jj%bNa05>stWkDwCO((slC3d&9Ha#F?* z4Bz_CQ4t8#p~en`1WR@oB^z1XG2B-8cxF%Yu8AIY&u1o_4~icrowK6$d=FDz6il77 zxwbDIolfOk&E7aoy`i;Ci+@PItNKZgRu}*7L>*@*LPrzJn{J1;`KIu3>PVdW{YlMN zOR+)kd*E&X^`$6zTJKCi3jJ-{AbQNzY>K& zI=~hZIv95R-ZzK3*UG@SVdQ;!f4Hobk=XJIvr_~Mg3C1IeZDF059`Ti)B&aK z+SOMhyS2_5kaBzq;OkWrWag~<@R5l9j47(MnwhIU*J9!aJ_lkEUe}hpxZMa_FWARq z*1PwYul)Ke2$c5%YYbACVI5VoGNvEC=-nI1`1VY&&hLb@jV);t19)MLSzSF9JSk$0 zGkduGrNLUYa1+&7>?I{@evG9@O3ZkY*>t8LHqF#@dvh}`F7Ew8p-K_(Ne&K1Zlo$4 z67+jMoCLjm6fRS@OYMhzSrdiJN!%)>O2Ki4zfiCvkK9%^{@o%W#n0lWHie~9v`Ts5 z;29f)!$N3tsUIfG5H@tx%>2EgxQT8V3sm3Mag6xBb8FlBUO$u0MTl_oS&wK=A`dIK z^KGIKb0ix<(p74c`Hkfa|7krf2i?!&b*1Ci`>{Mn>=s;NJNcsJk&$TsRAq>|Q#>K{ z@&5|(4Qx~W!f&FlxEe@(@(QOoS?ilEw*cA>#)TXlrE0}iLenb(-dWBHm)GDM>2h7>n{oWDJ3l_{PH%wNU{ zmXW`9-TYf{WV7^xf2V`!HGKQc7TIeKRIz)< z40)120^H&3UPM4^1Sf)D$q@d$VNKH^iL{%GlRN%)iR zCw-xa2Wmd>F1Wb37#kY{@zI>+3ltP!1yc1zcRO7S^pNU-#yZ|#mgiGFKJ3%7#Y#Gv zg~PE11dhkl92S$Q8XT#+|HO@*GS9CepSc)Oh;Pd8G@^o-vt+yUO%POCyp3uToTh6s)PSlf012EvJm zOoo*II}=^lJGy%4ykP;fDIl?N(!92YFmH0>6hIfz z531}}IG_S(WRLlCbAQ+FB`>gcT>~&Ag|1SI{kZNIk!4M}0BN8NRHJ@MU>p%3xWIS$kWE{EcCz`UU=aoTq z>#pLdwgutQy0v6?wRqC)-KwYJo%oHtVO~jV1-`rHWfj7prvmEMrnA+ZE9u71#b0-kdNlw>4%iOh!I=E=(x^m* z9$27Jm!c!Six&=~?_~MhPf6uK_}q6gkPr9r#U|ga6&xj2#e<+Dv> zko1FzyUn6lW$&4q#JImjqeu3J!&HU<2E-jzuwkN56s{ypWQTQNU@d8WC zxxA?;SPR?WMgI*k`wG&&9mxHG=}L#6FjfeHc|R@#UJF+psA|zT_T-wav6!^%C6z&#hA;61& zYRg@|d^PG~zZS(DbuE5OU?V)1#va7d%ALsc(7{9N9c?Nc#7jJFFEi70dO+J(mRmz^ zLZqJ!QVJz77iun|rJe*e74Ud;y4=wRPFBDXxSf7CbzeY@PZW#gyJ4o%pM=< z7G5Q7SkscfRr&&A7x%t4a?<0ITmI&4y$F09SS;{}EfeL}N43NEs9`hxf{<@C< z!Xvl*%*0o_zec>jmcb$gVO=VXj(b)sTS;Myb!!PN)E-5r9GWLi#!pc&-!p&NZzFy2 zhjH5GvasQ=0>*~Vao1ZJz-Gh!KXnSsf9e$64qlYFEC{|LgDXv=vR$JNz?&GDnG?ou z0X_(f&0h!P=H~-@q-GuF-XBUo(NR&^i6a0&0W`Y!O-29CNkF60uOg~PV8VGH_h120FMuS}4k}*^bO*tVC|7-S^>BLW#iG)~($mq%MYg;*U?rfCrk_8;9 zr@&1OeGQ-XzP|O}4T^&=uF?7DsQ&M*ln-A+o7tE&fK25ux*D}g2yWjF6bC#M5-Cul zfM~$9!Y3r$|H|JB6$@r_x;`;1me206WF)t%p1bY!_n7(I z&HJ^OJacJBdTGQ_B-2T3kyr*L*AFS*=YAt`@!S6zkEKXc!h(5IGM)Y72h8Zr&-F)%abE6u^Es-%YSxNjy$g0N zC#T~N6k2>^kGzB4y(Rfq2Q$Wt625dX`SNgN2+&lG|Af2JxruyZg&2??**dD~?W`*RrMP~GU%W8FWY-D_ChsHMleA{cl9Iv$Lu&`>($v=^W+hzW7Yjz6b5wQd!ZD(r>k@E7S0qREJ91Kd+``U z!TL%9&Ac_)REqs5<;6pD{2`H`0;dcRmz1otnNiD9$vav;pJ}nnPT}4YEZRNUC1fH| zL3X)G@UDOK)XGt6;k)&fYUXK8ZSt#nGx7mPPbj%H(cqtL*c)AQOd+@X_mIohzsxfs zoJrrX&aZy2OQa}8rUKqt?(stwOH@(RK;X=<%aS%S(ui+@$ozr=m?6L_yj!HC6GZ=V z?0d**3vOXbS|2+x*T76r<*^naQz_yB?&+MR9PoalqXW!{R0mNk@PNL2fdpnof1G=>_2NhP7hBRg7_C84{U^3uT|3<@ zepcJmn^N5_v4qB99oT6(mAvxhbGCm{QFl(Eu{pp6nEpilCw+I(OCT`&$1j+F$G;?O z$ei;jK0!U)F3_ia-u3#h{ArvH-zH*Ls7d{dp{FdmzvaWF%2(X9aT=$J?%f9ISle7q z8WRr(v5{~4F{!TzR&!i-#{l1r^S%0VT6tOKP)9mHNeqFn%q>QTcd6*62+UW*XMG?p z{Y7nz)qyi2*lnm07;%Do81&IjfJapi=L3dh#1Vj3PaFIDGiN%#;~q%21*r@Wa47@N zq%Ib13&0L>;F^q+h-C{Z9+6uce>Y{q9b4BZ@y%saM1mgKc;vPAi;N-GK!i5_FPY?6 zis$6H_cnbbM6aJt(K^hm4pBeEzntgtsxV`bd9#BK(-3-AH%zSX<11yZVwm3XW8wIn z!w9{%NKEvt+s=1F;isuBY%+6Qv#;gbak}=CnddhNH)UXirn~>bFcsSacS`lAa_ZSd z(&5uKTd(%imA9RE>knI|c8ekeJ_M0f0l00JwWqna$JcbBS5d+o&F&A(t;@P%umQ{g z*_2B7D&i6n6`6FInZcRCl(X)~2&Z9m`pw96bl0jycoJX6DdAy%$5SUdwH^-LKmOQ6 zM!C+x?P_~kb<}aXGCguK6TV9_OP6ARQ4m3gz~p4g!49@Y^F1oe0B>oVJx8?^wRQJN14 z;yGi0EsRYiNgm+Wxq2{H{U#46AR>~8pJ)U0rYnc=b*o)(-=1H_$-LH_Go>t6w`z~2T@KiMSE-{5r=HXF3Ol^>YXvRH}c>c(CB5ygD9Ve~^A>EEY)BpWwedH7`~Fb_V4= z>347a73GAFoON2ZJ21x^)y{nMVlh6F=rxf|L+0i}#Rx>Kus$$`CpP}Um@1U4u;`Ew zECkjSc&2oC1)bt*|K2f0ulDwunn~;W#Ds*~2QSS8wqDRJzkR!4$^Dv|nv|Q0&PcX+ z>YoyKra%KdT`Kj+J!AlXyvcE2&+BFjc;Vz16u1k#(rexWrnRykKLSGZ^REQNbGxrI zJf5SNL2Am4RsE8huI|I4!zfS(>W*o=#_omo7EW$?-KLQVw5`&#&aZeq^i(m1We;fA zdhhn}m`^Ia9Iim(C$6!5f>Q=1CZo}vel^+3(}I{HgWkViiQ7ks+)C=Q9kZIdt@{^b zUF<~B860MN3Z+`vQqTdT<*Aa|C~N1EZVhOUOxRtUBRk!Q}yhAJh zl9|ij0Zn2vuOHsY^VH&7if2;TdZ1rAi>^=O73m5fvm0Qr5SwIBZP;_q+NHA?tZkp-1-&*%+gE%3+(3RrjnN_ z5H~A5*m1WMxf1YgRGOSQz!tM>|E@B9FRp+SV zn+fw{74TMCQJWc4jy(=l!eTA5m0C_}cb=0ZG_utjY>=|CijB?M=-NLhUzCN(tosvj zrd-jA)|S=*frlXaz+j0`qvHgfkJbK`z)xn?fdqCNW{ma?GO4Soo(`$f$J29h#U~=j zzJIS!jETDSgT+zfAvc&FAux7?h(N=`zM`n8sHUa{*v|sLJ&xW6;8RWl3Sq{%V+SgeYero{Xq2;@$lOfrgX&2>F>_oj{q9$FvPk2{IIc* zwofBU?6lnKsjd53SyKcF6Qo^*+?U)#p*bI$muyB?nsfRK6xTWl^MyPd(tXChYq{|M zeA?}sP?m)Fe8Pqzr`J~4@T-&|!ic~p*dl0<1tjAeq@XauzeyC^ewk^36bI?Tus_N` zl&dK)!|eO|vzI$K>3r-nFfIjb5|Ac$;~}J(;41kCsFZTXet-)tCI$yhH$u>(x1~(^ zPgc%4Jj+!6XrlwH!(LQ}Srb!10`9IstZfBd9`GxjkQe?aCs#LT`G2hRpHt?=#l<%b z0IY`^rEpt;0&>mvM-&(Eu?ARsyh+m2g}yOCFE17{;Cf+;$?2DmV71KlR30N}MHsW3 zwVbR)#Z?ZvZ8;8b;p5>I*4mYM3R~-428{(+c1ChX@li?4Y}}^<)z9y-;KH$QIy8WO zXH`+9V`Kg0<>~dZ=N&W$g5-@hpwXgtc0S{MSf@(!S2Zf??>sZY@v^duhI%jzZZvW* z)8dty;e}~<;PP&_cCp(-b#vxvvZx}SE_34G7XS3fG#5HGObG0w$%oZ;1`9E4oB~2g z{Z9uI(u>*}{gC8Ho1Svp@)>u=w~7!*Cp_|Q*M5vgHT=pbBdjcJ#&!(-!)##|S&ucT-q+AGwl=KUupvw)4azN3 zssK+~U_uQZZe#Y4Y$$4AXlQ6dnK^$xp3#9g^Heo*uLdtEc#F)MC<;P={DWgDV4~Ab ziiR7-mquF2)%6A#pMh*d$m&t^aoNwGhT*648bAp9o%;8u%7dk5br8R05PtLU2(*T? z+)uDZvZZPT1qD1Cs~?xS+E)PQ5~#SMzDNPbB5auz?>jTI#%5KgJ=`l@i$BGVLA*E^ zWjc>^{hgUVuH`>o<%&<#e9Nb$rj^W5{6*K*6?%1qqL!Fa(g>G+J^v%=_a+?<{4(^> zHb?P8lvm6B9fm}}pMvAR-rYS`=J$pcsR~c^g~MdSbco{6q}s=^uDxO8lZp{scQXu( z-<>YTmM7g3l-LCmNvWwNGy74GW?Lv_Pza4|PVX!4^P5q$8NzESY9@i&m|8HH6F*=D{QC9F+X|=HA+4c?9TrQi6=zOw;wAwCg9S0s`#pq-n%wpq z*>HX90}_lgqKL>l2m}kWV^#J%*|{`7pB5yM<>qn*vOM8+HgBKZwCLFY4{W#{I7maG z7;>N(MaJmPSAHvyIJtxNtvdiq6l;Bb9hBBpRaKnC5qjl)P-Phuipo`bubTWb1pYL+ z*xz4e6ZbTcjfqyVFy<`PK`TXHtF+uHuOGZ* zb{lPff&-Q@>O7mSB*VbK;A*Q%j&*Y50m&Tu3?}t4v9Ydy+#Xho@-Z`h2@razg;!Eb z?}*7aP8hO6lj|b`s@+1PXIj^bgP(J&KqZDpKwv#zvpcPA1MH%oR{b&SY*x|}6L~;_ z90*?o_ab28Je%(SU^9Apd;oz#8T^j)lVNh#gr9JGhc7IHlO+3^s3=shPNw~0oOd26 zQLn$Bs=xR(;7(*VMmFS-)hz6i9d(XQBywq#B%Wc!0c#l(lJf zWT%=LDjO1xkTpW>M@JDu&bZQYe2B1*-Eo+>)$Xz*@+xY|1t*j(6e97aoTEWbWc{Qp z_O`Amk`;)KCfw{5y-I``Ftwy0)!qWEHu0_5w3c#X%Wj&}7mmdUDOv*Vo-A0Alghm> zf-2#B+y&!WV9OA&5TYUDWqu_;v1Ujh5IWXrPNUhVqJm*R{?Q-Y4O$Og-VzcL;CObg z6_%Anic@CO6;17d>UC&Hwt8-nw;Ps|CS`AhkI-xS*4KKtp@38f_RMYVf1d?S3FqyM zX>74{mFK$aBFoQK~urgHL*CVWf z3b-I=;Zcb^|Ex0%8SR2N!C%P)1-&;pCEr`lk+1jI!mo{bAH*(e(|__<=on#H=8INx znnhT>DCV_sE+MRRc{d~dpp|y-p{}DFul~*KQK9DRJ3iRI(Ii*rFAuB6YuNcL)X}Qk z#*0kxXP5oJF*PKIF`jHvb4)oE8!@XWMXjBB124LYtpZs+bpdc6pqqoAZ)SfBF8R0d z!0+E{rtx~^HmQw8t}8A0c*#f~#SCD4<}9DZSybQOKUC!a4eRkryY~Z+va&Ln*R|oJ zWuIewc9|Ufzz_1(`klun!~M2v-UkOvo!22hlqBD~+$7fT*C;ThI5#(waQ^$t=4{SM zEQ3t&%fRtwp6B(znu4jn|}pbdqSJL9qvZRaf4A zEUoE+K+-Q1?om}30f-A9ZO3IS2yfR)Y@KgQTX@XfQ>3h-stQ=7hqIMARaNXbA>uiT zuU>=yAkc(@86o50YaoLWT|3wuLSuZvqtX~1nxu4(;9dQQr}5xC^0|1_n$85acfn~v z=-LCp$a1{!!$Li~R1UUuoSK)jyyGrRtzK*Wtr+!RvQ&F{B_(zWc1b#g-Fw&DKL!yD zZ4wKE`Z~GeL_|4kyT8yVo{Wk~FUI|d^(#yyyHdXe$xxc2D^PhCraN;Pr8u^Uw;yDYpFCyYj;4b~ zKA>A{(ZP?h?kd!n|CYjqxuf8%k%S5iIq8eHX>#=oR`m;@2%A*09`vx_5leg zl_-gbRR=@oU|_li|Ct`P_z@Y0BX6%+IYN2!jsHl9$Qw8VRW9E#OmCgTQ~gCjn}d_K zD$;oBsq_d39+ni`3<$#GV{w#G)r>EeAB2L@^7^l0-!=wuZ2pd5xw))#I2PWA zrfw*RY51+|px&_fDBv(|Hc>u0{GQj+68EZX^WEfBuGaD1=1&G8CTRRF$qE7UlEN!w z>kDS^_Wdsx;5VV8Y_f~4b^26?f6t#eF0)=`gUMd4QvVqB%uj};7V)ka8U@o1rEw^o z9Pd2qL!uP9xVZGn>l+#xKo7Wa3U*u+t47NTh$TQMG0<;lY0b}(=;UQ)+EOQnb|~=< zv-ZNn2%jxyf08mmbNB}ic0mFwxsH>;VHHbnU!On2ypz7`KYV}Yw)Ieo0IXk7f}W2K zfOvFP&_u1=F12lZ(GsKNw=ZaG6hO(|xL-@=HP^sHHP$hOkC||@Nh(NsBI#dgDvT2(Uu}h)fvt0CI7K)D%r04WX%Ulf#}1Y zZkW)m(Y8^zSi#zc!>x|g7BYc_(FPPwOjA7J*wx~6To_G4)Wz1Nd@&q8Nujc`X?+<# z!mGil*Qw79291aGyi6{#X+51t?DGxnOtC&;f?8nJ#Cg50Y3q??2~$5ZE9@s6a`YoE zg?n}t<|2pEAU{XcU%Kd-4QggSz11!OSc!wGIywgzZi52@u)Yv^&RC!$PDtqWFTTEY zit5|2Z^YBh%ls3r2tUn-WP}c*qIQ?=di70&RbYMKto-F97Y<6X%AS5Z@t2i{M7CGl z>X;`%Dp5<$&K@4H-%Ui7)CsJY&VMUwh`T062t19L(S5J%=V${)>bR64U9lNu*Iv55 zdO2?EbzV7$j(jame)IGri_KjHBD!|YMK$#2W9x9j4|<{4{N*N#961Y`%A<8tV8e`j zB(OFr-Dw(xe5(*d=pZ7u@zECshp3`GwfwD|Y7$urg+)aJ*7axTXjP0HyptP7>h_XAnwyZjAa)rQ`iskz<@=pc z*C5`OQE$b@8JC?ODb-aDo1ewwatB(ypExg2+XsovemA-d$TAjz@i{DHgX@l3@!D{uc8Mz~VrL<~+5?JbY$X+;edrf93kMU3Yy#vbhJzjHB{6cL~thSS6zvOZr!Gm+b@45eU+CZPEIy9 zMi+<=v>=dE4jE!HJ1#T#^qRR$)L{=+q7SAtvV3U9ydFr)N8j%-Ym1%Kl0@l(ouTJ? zQ~=%7#lRuv@NLf_=8~ssRHc8jgb95J#uUB@JQXR;8s>~p-EgB`hZtkZUui}4N`>2- zcE06%CmU)R+=!wt^_v&_F**yU)!hxBIzH<{?`#zQ5vVXKD54^F%n~qOiQQU}Low%M z*Hp$u)K59VTx4k%#GVO7^}TzJKH*O*1C2efmk<G#%ztwcp;J? zk8q=-P!4>w2;GCpMq5w&(^((0_7(RweoEMVRzHod16kAQC$Y~)Il=6q-^nNbf=Q57 zWw}z={MyZP1$JpXj6M($0*flqpHuDp(3V3_nkV>{dfD@%T(c#W5d`@})7IUn1DPC% zTaH#TuT2W?v9r$a-OBxA^AO*T#69Zrz z1Ta!C5dxwzjV2+QZa+W{ql4XF^ktKzGYS`c7{QcN|9B+k5kyjtYv>Gu7O_!fj#nJ9IJkMg7-|dGmmm(S3Y~7P3m*2e$^r zOC_SF!X>c@@V_{Qeom#NzzG5C1y?JG`^p$4i~v^TQ=x>{GIDZi?2L4Dbfg3l z25Afm1Ju~Um%V-_`_9Se^E(APi)X@_m;3vm6eHwcT!wpqM}ba(11v2SaCdK>LJ%Ra2d`pcg-0?^GYp{G_&9 zFHLmXpM{0Ugn4P7PW`%ep$n^Fq8of^ey6(ghD>b>*NOi~h-!eJ(?Inpg$ z(XX;&?`1She*ilodls?uVoe`*Bu=T!X1pA>7;=MGSMwl`cY~88`FicI+SETg@zkD( zS>he9OUmdtc6+M!PNc#@2}&7o;U}3FuJ3gZhkt8{K?#zt%{y<);^7WBI@w6>Uvxlv zoebKL*d=`pfKwqmE9`q%5lEl@jBb|Dx8aHoTwidk0oD5CzX6_*kPsCW6|jdfUK64=)l(_95oAF9DAG7GJ!m@nchYXV(Um+t5v5$4 zi(yxnZ_PfZOvA1T4q-p7o#&Dj<`t3P@k zPww--IAx3(gCQLdjP!+3uc;iNA(bu@}o+N3khH zL0(Hj*T9>M^w__h6idY8)sNTjdg(g&eSXv^F%RJe7H8jXCA`TK=xiD`b!gNP%7}WJ zGG@>F|KU7MgAAzMjkCfxhKbUZzqXgIPdzcx1fVysXYV6AQpH^thfRAvRcOKTd^xRe z?FrsTy4;;$Ax8ONez85OH!E=ED$Q__@+dv{*sUq(DDeiL&FkoF>X>;ED{`PbqWvJK z?WGH?^9w>A?^oCOY*^7C0uqAG3QKL^tKQFd)OIrOm+j-VqIq%T=NZV|t`@;^ob>O{ z@F6ue_PB8Y0!g!4b*Bx|YT49Mw4HmJg#^SLCy#e-d6E4mY>Tl@iQjrHfFQ;aO!k&Xt*LZ{U_^#i43wT&|?F zGN<$w&TSt|GqpcV&7jAFrYvu{a`i#jR1OKz3UO(?>gnW%Gw|$D5H;ehaaDUMR&Vo&^~>Zo_RwaFgO?s!x#lZ%py%j>9eBx_ecWA5^xaOEj=$XfY+c=A zS?lC2gxGc0wLG#poSmQ|_oG=EuC>jdg#+JG)Xj z)Qcrr=J2jHTL9|<&IvGwnb`+qDL?YR7jEf>AlfoNKcAafKL?;700xOYU#eaUpKfc*MoUL(2^@ug3Igga%W0*Eycn zxSr@_)(nc);j-JT<#;h89Es_59m@{oqRTIP(a3OmU9_~7l6Z7m9!z7?fCzz7(JQ_! zn{n7~&_V4ZT^`vXLkK_(ZH@A5*%$eOMfG(sFM&1|mfN!k0{#xM;%Xn?}9*dBZ1#a^{;Qpyt?E z(IYvwOMohIAPMjjQVkVjh@~~nH!QgJF`!Yh6LA#|7H=Rb4(!obK_Hpo_Kp{8^F&7q zCTe0S#r%;3(bN;4Ln$Vbqx&MQPsvMDw0=QPsSkXyZtRl|&-6d|QGAk{UgY33Gq_TL zAS32{WDNNXH?v1&>jm$1q*V)ZCK$~|3=ikCuJ!VDMB+beG4T0elJWxG$l&0heo@URs)Lcelj zHB=r+B2F~f{?1M`09#L$*ZVY*ug&)3;HI3ByHNZm*1q{}xa!9h(-}m2iZ-;9FP&yW zOxM+!$qL*R?t5|ArLh|-aqI!fDmY`eZ{7`dJTmhN!|D?mK$PEBEF$ev?dQgWRdPf) zf^jSu7y=+DFE0;xSU$I2=WeZ2=3M`^UIi09?CPCaY{#HoMlHYq&mm7XJ2pZK;Edcn zEqwm-6Fi6SQWn2LY8-pe+_{-P$cSpwH~o~gqFoeBz|q9YyEy(hchmh^!)Js?5G<36 zU{;Q9V{fl6kwB#hu8|1EX3>Gq2p#&%o`TgNTroVrhP(aZL#H}~wc_w&chh1RcD{f# z?Mc$FoMfV3$oTUQ={}4Ge;3)UA0mqib{>^CBK~r&r@gDP`D>OSzW7TGZCaja5B`qP zb_BK^4ogJml?JWI?T;pu=O&Yzcyt|D`;Ct)r3|YnDq;g-KvpzeC=gl#_ARJz0D3|} zk#%~M`JMrsU5)_ubsh$~Jj66po67ybBw@+y&EyZw%eE4j5W205aDI9$ooJ453&$ZsgFPANhgvOekY23&$;kgnCcf%9H!K|r z@!-;5Dq!n{s;dt=doz5h^j@x5ySWlg+v6YLcKAj~IWg15e19{_u4xK=M^ZetjhZkM zuwX*cr~m&>90zMVV@{d7Qq-W<2cwUU4Dk>or=Z3|oqL{v z-~eFk>h4Wm3^fsY5P%BP8)b^8rdM9ZNsEA0=KF##6kkAdlB(S6PG0dRm*DB|yE2Nn zTZh6|J42t)Ix*HYB zqXoX3%7uCAWEFNpzdz#E$rrlCO149=eX_{>zA%N3(RVm3qtBxcsSk`)bk8o@iZU=A zTlVqKZP$yaK3sG}A|oKUVPYCKukG#W0jUm!Q+v0~{@Kst-}U7o4`)lC!k^g1 zT+$T=ppsZL=VMWcZ|PgX&SePNd%`*5pOv*O-%p1wt-y*rwU9{unw(*JKJ>#0vGhGMZc2ci>PoG>-@{AWk)MvGlUnavQA#lV%3eO-HuxBR z#aLo%wzHDR@dS*cpA;;R-V||EMU!t8w_6 zY3khEm9cm&%Dj2$@Gj%k&K7LPEg9|GFmCgU@sZ>(6XPGOUg2^!$nM47UYmQ#>s^zV zH~#vMiYd`*Ddcf%;aFMcM?8c~I`ze>rt3Qs-)aYBH^+_~$-u=kf<9eTJl);U)P?*~ zO7oLmie_Y zqVLFINvsW7KjfhK>1t=Z9v#sZ{!B(-E=snMfrf^O_{HOW|5PNCMFsU`>Pa$pR^2?g zJSj2F*F_TH`}4k6(jAx)f2Zg<*klS-E8UM3Kpgn?9jKe91FQ z-Iune3~N!(O4OmgugT45Ezaj@ZM}L;Zz<&}+R;Y%9LHtgzEE}YBYd^m=YAJjvo5L< zfuLYy2Vun|{ zJy6Cuh08s4_b$ayHdHASF(~L1>vcVHX%%lUNg804_ zy98I%TW`tqeG=B@fSUYgYX0U_y2$oC58ix#`@KHBU*>gGl)ri!-yjyba; zdV60C^vb7avv02Ow_bE;zc?*3=06$+b<1pj+eXmWotv8L0zd=Zb#ANP6V?7`n9Y2c zf27=`b;~9>Rym6Pk5fGh+4W{n5KI>(k@v^>t;Z`8E<^t`9mY2j-4?Tqyk~tM-kGGR z9!`p$U8I5BQ!X;a4}rwjjntYe*C$byzUbVtZ(OpDkTj~)_*C>h!33Dt0&L9M85~qr zC_J#gOo@#(;v@!rJ+R$%)f7n_?0GkD6o~M=sUu2wzK%}sh`OPnmSyUuOd&Q}RD z=c8~wAKL|5%{I!V-&8cNd#HLWH1{t0Rs3CSy1lw0gGDSw(p%ZRy`u~H#Au)5qtI)H zC;=nLUA1yu+%yx_9O|lmT;f(Sq>WSlk!a!UC-)cK-LWmRa?B^*0E3D2t?oP&@DQLkVQE9uk5q9u76+*_An8kz%%-Kl@jKCZ&dGdnp1x+=+|U#@0h1d)OX>=&BB#I zNG6bv*tdPRegD|C^m&Cw;Y#$#UBFEUK)_`)`>OPSqg7IJ0L&EQOn@%xLyR#eF;KYyR39C&+mOSL z9*mDgvy#R(;R(D0N}u!}#Wd5GpwD0(q450|3sGq;`^7NjZ#{i|$McUn`3P5NbbC2O z-f!)LbiKEFJa1Kx79P)PD6H>%c^xi&h#V@(*=4YM1%B-nZ!NUz>yx8ipGq#{t1IGr z?Yu3{k8=%kq@TFf8{Nv=#+8he*HyjCjv8KWG>LjkSq-DBeAGl=5U(ju*NvQ3Iq&za zK@F|rQZ3CQ4{q?IK@$3Hq+`mPanwx3uW{taYqkxUnIg}nSRlaX8D?wD!S%+$K}Gd0 zXN;5AkFx0b&SCo~XD~%(>-uv2ww$ED+<{0Y$>-F@`!I>)m`B9+is^ynV0?T(%3ABI z`yXBA&ov|ix4^RLGP(F0YwvVB$DEb0!F%cE%@7uZ_@Ej4?Y+I`6(_;_jHeK&u$M*q z>AR-bcdZOCVfbEs&BX=WD(ZdN9G|VMt!pe}_j4rfuJ|78+;)S!cELa~py~6K@+tnq z)1-5$&RORrs>;I)c##~0K{`-*x`9Hh-!Q`oATwY*F|iBWX8p)dIJ1x`WPYj@xBeSo zh!4*MwdM}($M*(yrz%=n#AIZnWKMwOi;oXRHEe8bLPF^_ zz0eACXM^#H4E5>j+w=bBo$befs>8v2*TKur7|&0kF{^CLj$El)`@gNXFH_Wuz9x%~ zGRf}S8p`U1z^2!`?f7$eUm{R(SnqOpy}$aL!{tx%A%SI{dqGY4^EmCxjHb|10*~7X zKYgAiKf{>sxk(=H24QaAgv0oA^3z~@UiGs0DI*K%O<_K>Y86UcN=!z8gqisjC0#-D&}vm!kX5<%pruMhI-m~XkR;L zX~&$H>=X#uzS|d%{S`Prv2j%3OxDTiGKS^@2ok)x0SWC%9DU}sa><-;py-h#JVy&Q z?Z6?2n$XOw3AX@KuXY$OFc1rA=N5Et5-&%O?bdpb zrkR#&SK$-`o5NG5jSi~g`fHctgLg`o`L_J?43l*JjQrbuH?up5V-miC+J8BHlKO2gt@L7sk-c?<-e$Q_L-?B^9p(_q%TWX;0B08H%SloatC`O|tnv84bIrKK0@hn#*^IE^5=LbJHZ-UfZ2?XAhz>2cx^SMkb~C_})dRxOZftk8$e z1P=xW!ES09K_9X8!Th}Oq|%fPuN`Iz z_+U#D$9UjYEn?=&bwDz=d<`13p zzVhLr!T?pn^LIZqRHMNNC=~)iG0)`Q62beGSsXFm%gkcsnTdSK!+0@dNOY_{TPgf6_>-=aFI7}5MXpzq>XSQ&C?c=^H1+ceDh7TN6tER^<-1}mM@Vqx-X1m-iWM*6(gvcG0WYUE` zb6V|RK8^}Z%Y?t<{EW=}@%%{&-O`wywRSqEwNA#nxn$RGz<;O_4GWeREhfmlbvf3N z&THzV|7!piX5l&)4Die($LfGu)M{BP(@;|bm4AdJZiM6q8JSOntG~@cdFhB_DO4H7$nges?$Og722uf`Pt#DvtKU?#eJi2@*Om1^BB;td zn#V!@H^^v6YH5sR931IrSYmc7T1wU+?-k>a#qMK-~|P zDc-RhD=HeUR9{MX&kb;C_&-_(z9-%Wl-6nwDK3A?oKm!i-tSM_W> zI8NNQL6O=*ThKI7MLbeE1;SY55rzd4k=n%vyY&n2n7 zsfNBi-;VF^JxbLE%}C)z|CrZi(*amyCxT~L1X(&pMMDF06Ta3dnzyDL$rxT{@gW&H#+vWfskfh-7-~9d;H(~5*jp2Q-twL@e|&)S z!SV3YNQdTW^4Bmy;?FWStqLD8jDdaK5LKr=%ip)3AWZcoqTc^f9L+nRVc9O9<)g?n z6Fz+S0EoifYpeK{)Y383Z{cH0%hTjnuKkdq? zUb@zzg^$QZ%4^w;fII9T9bn2bFod;pct73)(r~@i0ypUkl89b)J=Z+&6F)~F*UsoM zgnl|+Zhg92dAfag1g{SGav927Vl1k1?i;GlfBLaWB4Y&ROz5YnYw1mtsrFKBAffr4 z^sP&gy4UYT6t(N#puFLe7q}Y|UTL+`zK9>lY`^xs`p4WJp(qB$f!QuyzUdgs`yT9J z=)Uh=pldey^M+nnEW{_Ug7n^Cn5tRk38&IUc?OBu+7;gfFY8J88|cZThMUd1$ez9$ zj5UqFk25XUHx0L($a5rxGYDT(J`0?|r1%t0nF$d)42=&x&H@ArJtWW^1Py8bH)(;{ z`=^zLf$Nt#OGL7NJeJyV!4qk9eBt);g_N{($mkCE6k<#?W2j?)#{nFyRtxmBplW6F9!=p5j3(@X@02&uyT_l2l^8d;9mi9 ztmf;i-1}ZSLnC?}3{xrNLb6XD4>G*98o^!)daiKM`agDzkj=1ou~EDT^*@yHw@Uxv zwDZ_gt=7(mV%*<+Th=ltrO4M+L5JGVu=vpL?S&G!6~?czBiB4qsC>qV5{C_grihc? zXzC_9r%#z+eI%5peiWU<$lebH@>ZBb{#DQ2u%)+`?ljo?UZV49@3b_OYiqxh$#r9O zUylo8`-tA~0EVRbGz^Twmri>U=TdW?w@6As|Df8|=w~b|z|`r#hrzzl1r{&d4*cZi z=Jcc09m@WGF<*2=v-q&X;zC;sNv0HY45Qt2YkE<#>2F7EYIG}5_xs&@8T>ed!LPl}UUSZ8J~6W_#6jE8hJhIObYfN7igU2(54lOQ ze2R?Kc7pzr{?g@1`QH?tion_>7xvMYqr`OYeK35d;^ zeWb|9Ky^^9a|$K<n9JeZ1mEU}=?)0 z-$3q)+;p+tU;ASv4~@1C)c%q-zUQTR&m`L_43@(szEkkt9=9SGz-RGOsj9+<7{dHv zrxf1d=Q*dIt*A^?m%{UR{#bwlYrea;FdZI_q~8s0RjIMU0AOB?|ARTms5|CU z{dW6+hAeB9zT|}qF{(<0>V&1v1H+M z<2kH;#P4*RuxFNQ%q52fNCyfbg_83uwAg?qZK!0B_y;nCU+{XY#p&e5M93`=WJ&81 z>jhrfcx=sIL;&&OcM_MtZ|KZnj%V1}C-h9VU!@-Q7h~fJ^x5Cm+S7fdWJ3gr1!luY zY}+>TsL=IKnHH^NrP>WQb(C^lv`m9P*&QLTzcepTwW{0}qZ?SwmeLtFah*!9s6Fmg zI7bI>`%&fo6=*k*o->=wKL-b;bxH`fHp$Byr}~k zR5Uc)3wl#(NJw%ie7I_!zvjb=`-^ZAQ;A_2FrLtq)dIwvP39dAnV^O968{ubV6c3f zVi6Oqk5#rmAS?UTU-H?OWg1_LlC1uau3#GoL)wj!*!CP{j$MKwvzBu=;KgD51GRw7(o3ntj^*;^kpV|Iw^&Fxp zIS-g+rKz81!^^n78OzELT(5{2yR7;52n6uvS1kFCTwS>wGe>iqe_NTJ2d~G&akfNp zhSQHvR&y-_0ZP7KbR)vN_2niD-^&pYpZYumTn-45Xg2j9AP+XDK3>dkgZy!n;`~R{ z${AS{-SyIl^;)+%09FW)YVYEMRStn71JpIFYnl-+9xv2@e|Jw0MqS{r*||=N6wLCU zeip3U%y1yi!-`u7uEB$g1~=qNQ$l&2mUEI@GReyFf{!c`Q7N743~_JNps-Tr#aHFw z5Wb>l!UO>kdCdaKL_%m0i+VwkE*Plc&3FhG1VV^xlq4OjwA9C%0s^kH79tNxx_DVv zhe$a7e@*`5FR#@&um3QpiX1k%uF;2PI^4f&_IbM1$E1LybE{ANwpn(Q_HkP0s2|zV;-7%$6Pe)MJZVcph0wf``6Cc-XLu(A5b?4L!>)JE_sYknk`Gc8m( zT@OA2J~%)RP54+am%snqG!SUabfx+!$;-)|Lvf75q7!#_-EP?$(bMPgM35Po!l~t} zvPZFg5JtX!Yp>Ghlgz~ByW}Iz=}{>Sy(LZ!YE>Kz=n#xogKoSx`ul0@vRdk0x#KJC z%$7&)-#-+dhk_V&x9;zYH>F)Erzlr_#BW1izwzu`9DDKp0{qBpkU=oxl9>z#z%7Y0|hF4bT!=D^`%R}P9IcnYBGGupECMoUca=^ z@f`f$%5xl8fs|DnT8c6&8ms)6<4GZgFbsNf#~fl&mVJONPicgz5fa#`>xXn%lY@)m z2%|4V1zbQF!rZvgw@>d7B^jCf5L1N^xk$Lo*r0{FXj!y9OM26khj}0XJhm3_iR0<7 zy{|xcm!$&>9Qf|qoyBM4F6uIlN};d26TIu|Op z?{GDHnx7s1g(6N`?KEQLlhw_uL$-eYN?B@T z3=MLJYI%2h$=X8Lznq^EbTR!pq$K}6Q4DEui0?)3SwxbplGOCp9qQQFxaQN=OzWI? zS_*IiuUzbjshE^oVWXtPUQv zs(;GecBXy85&?ylah`$BSd<3H2>EuBIh=m7elUguu9w`ngbLeg8XBOT0>}aeiO+^C zwBdP_;C5QdOTZB1Ptu0p+`<0GOUuAPiwCVTTz^_rd+4jKMl6jeSV1+$BMB2Cin}sF z_X8W|-O`87ke=3(`|E)DF5k(0LK8IF(?)& zf}QZF-#GJ*Zexp9!cdo_%=%cYy^6K%z)Hss3R3+LtrGTmR zj;ge+A1oy6C;b1WtqM}(kJ{)*6L}tuwyetUm;e~)t1r6i?og&MkjG?-zyv7J_3(DL z(Q~iTA&6o&t*rg!vcigK8~~&hVq40PjU@noJ;U-nZ7Ks`4xZdp^CTn^AcHfz3o?Y( z!wnPDWdgeyDgfR8h zM066}KKPO>bk$Ec?^YWjv|qpaZl6*4)o|g6P^DXm*uZr`y?=)a6iQZ#wzvu5mpUu! z+g7jw{bl2Uu?416H7S1yh~m%;WQ+VW;c`-xQA?_`jS{Er+F95(CNbk|l@B7`m!O0} z!5I>vyU}|qNeSiBt{xzWA(*021U>euQYS$6RRcz2xV`uvR&f3Q2K{qaA=%-K?%)!{ z3DaF`lo{FHcbw?7Q|hP4_lGUDw=&J{hQ5r1HAqTmnO<^g+uR}L3_HNrbpQEQw6}Y* zVo;@oII+5PHC@#l!~%g9;bDN^v-S4I82sn#xDNo6nLDg12j*^sCBr zNqyJrZ`Wo<4g`t|;@9@Y$PmTDpyndn+80JNm=FIrFo&XcKecMW;@~Rb;E2;v;KgDE zPwJ4hXK!Eoj9;hf&3X9xR;2PeYL`gK_wZ+X8L}<1|GqtLpXYzlns{o%gVY?8n9TK` zw*58c!BX5Ud!`@*Qi@9XnC`Bx`?lE4XpSB|hX#N#DKz=G*?OLy5DvxWAnW-A2gH?z)?a0Z8-}e3Bt${V9!;n5 zp%oBD2q755sjP3`ogVzG`g@!Qo#N1#(^(%vWBhTnHcV9$_{Op03~*tKN&>>O10HN; znG{dIPUBeUID}Z}w7HR0?I%&~FV3ZWK)}EvnBt8aLe@*r`FFElL47<;fFzYDZ2UD7 z9U?0Mw=-CZEOP$%;e7;*6=64~^87s~_iCqwr;b+GTiHa`Rja|TDr7;fVyhOqtW^>bzRKz6w)jJfXv^yHkoQ zWQpgr2DEpMF(PEaplS&H@%&BnegrpQ3rrp`)Kd5L_4V}hw6(21Z2FELGP0vwPzKHk z>-MRk3?s@`0pgZwVwlxLT8>yzRYa_xQ)yvuJIpdx6>6v9{@QML2pF3A zN%q4J$wRZvuI}GLV%2YZ`5<{q|8Mif;O^v=Hoox_2WM3PcqQj~zC zzPL5#>u^KmsC_7U85Yy3Cv7g5iEB^jlq7vf1+{RH{UV&x!a7maKze-FdXvu7X*jmo zvih_nT}CPTIcC4be#`forbXm*dLqN;Wb{(}2U@H0u_cSq>weXXf(?Omy3yaZIE89k zZ8myJ%3s`PX2s7h1QYev6H4XVF8gioA5RBM)y;%@@p3me5zGFvhJ+!z|I(~zZT*B5 z=H%)sk*|bXi-8oZN@30dLePQ1%o_DU;`;wR`2eL#(On8w$E*UxUCLVagea)_KV6Wi z4gx21svngkL?&&dPTUAI3V$X~T$l7ARaci^u%h%kCsUk1#sEb`5#x}4CC6WOa<7>u z9bdl07wujBo$#6 zQcZ{WVNjg-i57H@+aiX;SfvR`8%0_#t=<0q^eQDr+GhB-Wd^U_rhPuy9h29o2oF_@ zT@Sx;N+rq0kzK3)QWw}KlG49?X>A0LqxomHflqf@;h1Rehe%A(HN3O?q5d~~Nhf$+ zaxh7L3hoC2C8pW^^LXspvx|mrpA(VSiv_2_Q}SZS_*xzr9AR(F;E;Qzi|F3X9p~Rk1bt1n^Z|;^k&S+Faf-xjNqA4he2!@8{Y={^6SD9KtH_NA{ zn619eq^aYxD^Q!19K;X4DT~bggQP@3xdC3y=Uw)Jyz*7%A?D_x2rWstLA9!-IZIWB zABi}{yrDpn=+B+gw3uA^_|kX!+dO*gpO&UBOnvVW7Kwhs(PLHQqwly&7gkRA zTs8P_^o2zbz3mYt7hppxJU?8~PSY`1gHdKE-<_~)hMm&45V)71?XTj_UfeyOa*Q;N z)JGHIcqAHk&%#eTA4=)rvGja2?j4H_=9N3nF|6$p?EYZ-ddzNAgyI8p8y+90JLcp_*w20_DjJJSo%0{=Ub zfvwfm)svHxz`(##RcVBcyC-lZQ&wJnbaVu!ae<7a4Xa#D6iqQqt! z#JHCiLQA4{I8%g)ZcrlE2F!l zX-w?=b;R<$uiamd?ocM9Gk$5S{o{GMV@WaWlQ!Bc_}ePtBLmJCg1;9>0vaMX6#T!q zFaOQuiVdf(|9$aKOf>b;!zxV)oHABsNu-h^55?aUT3K6+=iq<|VALC0D=B1!@yjY% zB>kU{l^@7rk($&v{D`i+3T-h&UZ)^1E2dB}(^VW+5zqhmzGGL%x zMfxFViatmjx)5Bvod&^v)pGkbX=z>-mdUlX_t67jMNuim0h(4%mzK2uceV8gGvNFw zqgY$Z`GpLogmu-e#9=~3<}$F&Ra1)?s(Sd*s zR(T#G4rpST>^rpgRUhd8lz+QADH9!_ ziq*+(ITrAJ#GsRst`z(j9KMl0UgVq4^E#1efhK|Q^J;zlZL}TTcADqu($s2iqQY}C zi`nVSlNTpI@3#30RMT_4$olp3;sqs0g{RW^T;66b-`>HrRsDDCE#b0TlY>ES&ja0` zxLw|)V%qCoN6{HObz$ojhN~zsMYoCHo;ByKeQnS1M`x2;1>34N4CZEgby6m(7N)ya zC*6tg`OD?0?u5NaS^O?%a$eVSFWVOpuNQLFvGFd62M*58&QAaPc~3y_%Q`)j|9$kP z8vD0VS~@y{yGx4dkDDj3e>a$j1Y$G_kSZq z9rDlY%&w&&e`5!C%#xw&W(975AE{}^ykGb$6AlH==!vh9tK{(=JK z>^UON&YSr_Qy&t)mJf4^(@Aj%U6|V@V@ep;=WN+%0O4N!*ZDX&L5h@y47~$uCRZ7N z%>1KZ9Y(P9$}p;f(;+eYzhCT!N`luPe~tcsE`XtUfHMbq!7Puj$4m#kuTylwb*jun z)3!jdt@ou_`uhhd3%c(SS(c(BD}91bFpkLyR3VREOmZAdt>oVFwi^W_kM&w7 zNSF^H0=_M-BXTef7AK!RyB{`k7AfG)RvC$4TkI9zHGDq*Zm@(Ckp}&C(Y+}1EqLwF z%LTEEyam$_+Kvnv@H-L$xgD=ejGh!;Ir z#9t@}gmbH^sz7Tne0{aPWi)qk>DZ5S4o4oa^xj%ziv&}x@Ep*i3C%a;^+={?-XU0l zezftJ1V@1tTm2D{&=kn?m*L-HuvQ_)L+)fSk0aN+Y5-PD{zfWKPKBiUf}d^OjehqT z877&zGxC?aO?=(U{9mtiQqX9?fSK6N6km)wQ6s9U%UvN#6fjBj`}VpJv&(_ftOVs> z17&qLJeImypBNCLi06{{^gC)gUOT`C&y^B(1$=7^Dp?$&`f-X%!ZIyu$n;4Je5HGo zBw`IoI59ARTh#sz?_O_$na|GdBY4c7U_MOJ-utGdGyg0nV}4%a#mUU}3m*Z+hFu+B zhi2Wt*gms2rD5rn z?Y%sf&u?7M*5?yZ-0RV+t?pNX$3psp$b2-h#4Mf-hWsb#0ALzsH*I$o>S7If(qAb`if5v#A^@+*JrGu;NrO@K3sE8o!94xoP}uL#52GD^`_&rDsiJ z1J_73G~k(>j`#{k_-NpLILuLraG}2U)xcdxQ#~g!i%rvGKIDV<(N8Nnc8p{ylBLd! z5Okd|pXd|`B{kS1K7d93M}>T ztuqp}k}mRM-J1Iu@+SP+f!9!LNQf>A`SC9AA3jdr8VmUN_l2aVIemI zuQ;q06Isc;e;k9K{srmXTg20wnS4Q)Jr(g?kJWu#$`RQ zLk7_out8Q+OPntc|KlevOSE0)YH%lGD2w&2gLT9_)7!?19#%GAc69BHmyzD&-K@(2yHXdJ zN|Xgbhx}vJT*xoKD@Shy$3 zYOJlp^ps!aqxoKgO1L8}?yhcK{FFa8oF24YH2g@})zPjmHrfv9d~vvXO(sQwHPqSM zK76hE;&?PE^jJafs|g;+gyHt|(dqKk=k2=|A0MzDjF@RhS(|(G%fDQQRiBZ#El#c^ zSKLRdq)kNk8wK<=#q*K&o%>E)zwUP5Hgu?32z9zSuMVv7iq0>5wPHvKOoQKBMN51` z8nOmpsLTRSR9ha3cM|WEb zS3>-YT+u*@T1^`Trxx_ql=WB;@d4aejZStlGmmCYsY8_zutAF^=4?P|hQy;;kW&G%qIE@$_MLXsQV369N z^*Ai0?41x6f2*J+qVlEkQ%$okS*3mg%OAxaCB`cZ|GmQw0+Go|PSvJa7B40r2N?{E z0+`IL;UYkkk_>L&RiX4&>D1R)og9;(r!!00yE|aA`}UTXUFZ2d3AJJu1y0cv^U5;J zp$31}sIJSOF}med;#0xSNA&1df+mQM;BuzE6y{mQ=vi8}A6!IRLbJsy@?z22U`LuspE-I`7`5NJN&m%^ek*BDk$l>9XRYBRBw4sR_n zr{UId_3I%*I{*-Z`H}nUA5Y004Xqx0;nAf*Z`1Tqez3jV_fT`NBDc1-mX}+Zn-A79 z6l#FcMzgcCps5<@4dswwK@#qvhB<>&=AT*PkH7(q@%vY5voBoER8vt8yN0G;WI@f{ zXXqZd{*zUrKaw<-Osp&9Ev^t_6SFSaSf>~ZaE|0gnV!;-->#?et4U@4&cF{3gchtd zF=U%h&Is%?Gtd9@;?~C}QSM0bnPujzBuU+hiKfn`yBYByJ%}6pJ*nZh=&oBQ=_5t7YF1# zZO<)^hKGH7yPzEn{g^TEC7+WN6=-RLfNe`wg_ zS^5Ycr4oj!R!yj|1&WKRZQ8I@#C+mj&<)*fOyRDMHi3EbAyeu1j= z!Q`dBNl3@S%H(Yak3H{&S zsmc$cFnw-c`q-nU%U$k@_#|XSMFDe?L1N-jJ2;qsl7~OF31p-dW!##%q3tXxa%WA= zQ6Qm)?#4o?1J=Sj5O3k1=m4d^j>K7c{SZA0k6+l=^y;@Kv(O|;i2%iy%7_#wuv-<| zK*+UtZg|S-xbolg@(*V(JGDZ({lm~dMGZBX<9{}c67g{Mc1-Z*c6_)C zmWbbNf9e>MZN4A5-zF;FT3+=hZ8fhDi9;EaQf`hYWw1AR09>uo4K5EJ7(xc%WFjHg^AF`IwTuo z3}NGF8zq9;-bcf~8W&MOz=)(e6YE8e`g8P-#b9W=7lKb82LXT)#&g!sk3aN9w^}}+ zm0m(q8&;%ypj}137jZOKi0D-7{L&3ReW}Jq>b|qT6PBxilsaKh;_sjj7#Ejc zP*nY#G@I139SJ4FWZB ziq3;623v_Rp+YbZ|4Kv+kG1t7tG$g%N^7h?D7yKMW8!#5T>6Od!+p<+?`URjhej+r z?#7s3Uy5C6et0zXhf>Zor(%(xjYhoPO<_vBo!`Bsm}+RPCmNeS&Yc$fz8t%<$(McR zKSC~lquHiYIsW*jB@)*k%l^D2$mjbeDREYFFuf=-k$y3RoJN+s=2O@4<3ptV?nj`8 zp&SeqZ*OmJY~%(51sW=kJirYdEe@#eE3K?V1wq*A;Qt2TP=9j{Icfh3B|KRlsZ0cn zA!%NCZiumvp^baYC=9}YjraQsj#!~F&L!q(7#39gd9$q1k;9?!^Gj;)+XE9bH*xlA zb2z%9e_yc0YrPU?rwlf;Lq#rOVwi`C@47k1|eMT zMszlkpH|)fYdl++V%>Hm5`3D5wMuSW5W!D#8IXCqI`;1@J{B`RXnRXG)o>tgMe?X0 zx7qvQyW~63&qQuv6Zkelno{p2ugS^l`>Ccp?2jJ^ZU6qw{w~7V*%{Pi4A^tXfi|+k zx@uZl2M*0h2590l9+*E6A6V?M$Y3Q|TTF^F4uWGu`XBv{67U;b1f$YqQ0f<-vZ1T| zt;4ePwo{s2;}>B&!m0aF364gX`Z4{BM$EI%+L%4ZA34n9O~>h6IE(!4ZTM|tX~mlb zZJ$Z>RT)5cyH<6Kl-ktp0Q3>l1NObI+T4Ed8>@F^hIVxyX0w)LbR@ST1d2OFS! zZ~z!_Y4rSzJ2srjmMHR;h?bF<7*MJ(wd>Ztu0IBhVWgjp`vVr+Q|dU!`a0j)ujEM9 zpnXV)eeRIp^1eM><`tFOYANE4x_PnnVH&+%yI39({k)IO_!y&~w6cdd?zw(PD(zM- zct5u6>V)z%V6L%rGGTCMa`Y1VeRT!B{VFILZiOmX_#_Sifv0z%k;bN}ywh9K9A&Pu z?0Eux!k$QXY-8YV=aW)3Aprr%bUrvdRNnnKVDF>{q5iS_Y5J!EJlG>iW@sw4OvH8Rn% zihYvc%f0xH+P^usSGm?vK+0HJ#3K$|<(%SzG`AJ-w<^ZlAr6`PssfUJ=8>w(s zDmG>-Ey8*9l_)iT;E4+2W?BrUhy|y*dFf?wZox^iq;le%$<)Ml(?;v zxKal?lQvz>k&s~eR(+eq?3t`v&gwipfWBil*~>bQMaJ_+Qk@gEad4t6wb*P#uU~() zGy5pYSy-je*?N#kqxPZ0**d+L>hiVhnf+r!S$n&;ogGV}G-m9?9zDo(2Dkgw)y%Wy z;kzKT2^F~;w)b7?A+HSaKrSIFwnh@cb5D>K(^ZG!b?_bQ^iSRRUp}mpNPa?C1*&w4 zZFz`#J`N1?$1@JWo`sLkzlC}B=~IUtPJQ3%+rCw`?@19H-Bq*=dah{*u_ML(iXsm6 zBi9ZHnF*pBzyk^?l_35`@t(Q;E0|xDqguYqBzcuGj$>f38jtL0=LY~lPyuw{L1d=h zOahED78!={WTn~<6d*>-nW}%dKgYv%CN|>mMGX=N{$p8AE-3|?T>uR17Q;CLilV6) zD-2a6E=>{zIGWlC4{7MQx}Gh}Z{4+6O8|Z_r9^9$%(j|bcR5>^3j$P*AqLWvc}G

    p<52;HYGn^9G0g+17uY0C>=F(#e?t6 ze$+~p^aug?KNkvEAGMSMK5pLRffo#(s=K7tf`$?yeiXIyPi#ymDJZas?_K3`d(6mX z4AZ>MDEHCo*xfpNn$Y1sIb%e0Q%$1F=@IjdcO0Pjx*$q4~i?| z*<8;)djcB{m)l|)(JI$Uq$-1*N`%&0YxwA~MY0KhBod{qcb6!=WO<+os2l&<;vz2_ z+a?bhCP=ChF9Wfc-i`CVJAU=f1d1pO2OHx!*mkYUT^j&j#f}=gcd!}%aIi?KFmLYm zhd+j&*d1Cb@zAap(htcznl5k;uXvRlNi!Z{i;6ajuuy%BM}lOsvK@7 z&jZKFMCBQBjyxT zQHfM7=s7e28bR%{7i`BJAk^f1S23t4%ysM}IcWXY+KHI?Fm>niGCy&8$ZNJUN-y{v zwe#D`FNenGoF>{}Dtn*y?yr8`HaiVhmZ+G!OzQ{9Egq~!-{(E==nf7t%D);ORWGwW zyqqA^dzbRA3Mu&+sZ{M%s!#*W49NkjX{u~mQK^MCXp9L1Rfb&k7S3ad zKhuj3AfzN2D`6AjqcWT$C3`dIZ zmCX}IjGHo%vdCpS@{vj8g!Zb$YRXwZEL?0a&zG=n;}KjqFBD)n%9ZTPF(JRJiB(d; zVGh+GtllRBy1Kg~=?ePKvy$OCQCIm?9#xtR)>qRXdq_O7ib9Kn84&@esE~eDo2Gty z{h!?XbCj_<#>L}E_F{-#7)f0BoFURiY;{9_n*yfZtwsN2q~!lb(@zm4E{hjXxOBDS zt9XU3IX;=gg+I{M|6p5$OH9r={@&B(j+E3*fA8N-NGh?s>A4=`9hWD?Bcw6OQgH86 z=c$d)-9U%W5&Ngs2_4QSZi80Zf2=?b_nOOAKYfTwJJnj5Lbi{b%7K>zLVrq&sR;^a z6!U4+%5}1O;)Ks>m|AvgO*6kqq*$Hcx6k||UZ{GnX~IEJTx^!%Y$OK=B7H#z-w!11 zLPDDw1^@EJOz~nV9SKo?MWS#x7%gX4Qp_w)+6b_*_W5b6UI>ryU6`KmrSP*}srpSJ zQ()(?3^oIN&$|>`@!a^z>q@6HTD=RC8cl6B6VAHIj z0P@J^=D=hhP%_IQm!3r|gJnNX@oN_3yR5HrJIx&wdv8HM2YbH3lfTFQ`D{3Ou;_W& z>HSS->`}qzWH;dhctS^W)%qomHZBtAE7yJVA@S`HjUjM2YAAL3>^JN1jv|Vd>gBov z`tJL&d{JhN!CQZ!;~YaZ07!L3?@+>VT7992MJ3__Nkeio1qmQV54x?}6BmOoN~SzA zIR+~Z5@;q%7{UtL-h&|%J;|c68YJBKa=*RCBpmCU?Yl>Q*Lz}%(veo85jXWPvqbZg7`HsZUOjG=~x+hc&FcysM zh;f-vrI-LU>_FF#Zt$>n@2@y6sBTw?Baas^{izb#B9Y9_j<&s+`D7X&)A~U6%QPC) zLR<*8OMk3T7yf>RJsd)bV}{znMXMXb*0mTzp`ksR=TVj6nRi4%M2Hl0P5+AMNU>m9e{$qlCl%_bXn zpAS6`vV5I|*@k3t%5gmZ+d+DQ9x|zKO}j1-ySeGzb+406KM80CZUz_?x`t9}QMW-2bKOH%4UhbZ*O>W&c$^`k-vNe*O4fpE<#> z)XjwqLlJTW)L6|kjnsnq6QIc!=uH8Bxk^jH_ieqyny-ek`I@5EHfw#jgczlIib?UNmkqNoXN)eFKvIB=Eo<1mzSECI!0{lPfz_I z&sC!N)ws#dPeZfo2eV&_oC^f%T!9ZGMZ`C5>9hOz{fa<9uP`FDc0P+4b#cI2doY~i zU-1;y8d&R7NdzgBjlza|#hxi16XK=yY%Y@0a0`YX#8L=`=J>aVHmJNkk;?P61dyNk zJBro|^*M9MKvV%ip-tnsNB$hH?;3Z8QyWuO11#Y69J$n{B8_AI?ctZP{&-*>l3E{Y zbiP83D(*s=TKU>Vlq*YrRp;xY;Oj+nxq2lCxObj)Jo()Bl7cE~P(XMM#$tQ|O%H5a zPa1Ycl0oeyDNUY&&t<&ps`I>QvL1EN;Cv_vl>61(M#zVPs*CK^i-j5Hld6i6$4d$I zW3T-lHwHTXLU}W}{jMvS318Rw#d)urHG{$82l*WVAoJwF$0poDN#x`W59Og6}*fzHzTRl(2sV z(NGo?axov~6`Q*}@d$8B)3Z^toXJ=W?$M&Q1_NpijGd~{fA(bZ8PS|832z)A`++@! zWxi}c@@y`5#)zGA>_VHNob_?K$)-^WG)LfO;M};c-#0(Iip)1kcG&6ISQ|DK0IMn1 zIqHZB6dE2ff%W8wLw^p4s+{0OZT}jBc9kg4Htuzz|2bPHOqqq84yQlqUT$TE+hh7& z2en{$4_e1og%SeBL}+(Vp(7VYqrQzoiDZC)cWGAW5WaN4T1jF9ER)$gi@VP@_Em7$q;+;6Xf>wBCWfScPq$=&x? zUW%+0hw%Z0M=k&ZFk2$!s_R#lcOSGPh64J#Y7Y(-Mh)6|K0VQw>Yb$3R*1jx4A#7Z@saI&S+Q{h5W5zoAcv)$rsF9zCW_C#+FA7kFp$Mmhd3G9G`}h$@ zJV*;1b^QB$5Ex7pp9obH)*+B*OS-SmJ8gRAf#Q@*eDLn&NilIs%K`(W4A`bTj6j6T z(@Mcp#5b$*`*p92%NOh%p})>UQ@!d*GO#mdP`0&*4FC%i^gFkIDqf&1l0&BI+&Vam zKIbxjbN<4RXl}^2EeQab#$99WaM*FXbN31*H{^Z?lZf?eAZ@SdKY5GgU(osJI`@CjWrDiGC>$ow2^znR;0Vdjqn91_(q z$o$8_vAe&$I2S$QGQI<*`_$55v1!| zMl6d!2~Fd?AWCG?=@R_Kla<#~jw}9s@QE&0#7#qYzZhY3r*%b4uE#$+RrG`qhqYJyz_gIHCt>6G}5bDw< zBK;5&z3W7-DOO;y1Qt|!3hh=GM!-C+s7cj_Xu!UPj3|tCmuEcTOcQWki;j%kwifsS zEmmN^i}3i|_-dD9Wipk~;yV9gdEQ0up%{%aj^yMtuGju;uk5Yu^p<9-8#_&e)Hix% z_JJEOse}Lid~H9XVU&UPlehQP9{i6Vl!!11FrT@T9t#|*WrQusyD(=zu^hv#)>(KZ za!^p9p`wy>tnybV3af)!^5st7&OEL9`uef4vG`L=V}?{&uqXQcP7#)hSaF8%Dx@ zRCN6yYN=_dHZD$Yp)vZKelItX(sht28&(;hICu}h&<)C)k*sCHJ8TW=@rL^mW70On z>a2;0ak231Pp4c;9cbUWNMWHAl5qCTA(#@g@bt+puu7r`W7SE}nMwgzK^8JdQlb0P zT9aeEqJXZFS%Sx8QVuyonb^<354q#fpP^wOV1$xsy;)REWnD0kib4_^`GsivA}Ik3 z*HA7sVRL^rD2rrWZkRc^o_aqR3mAiuw%g{>o09)f9d|5*Yj9dUj(-jO7rzMFx@c3e zxwWtHlY-@^x3?Eh*RC79SQCYRICgkH-Ga_8R%y3o?-}R{=Z~x{EO@aM!Or5wz+;-Z{Qk8Hh#fTAKsNj9eTDWlFuz2E6i8mL=|X?i(IEv6fUUW;;%!N8wx54IS+J8k9E|w!kf^om7GjlxN>B~4iAOPf;K$+3tHo1Pzh{YmRy2u>-zFX1o1Wf=xUnjewUs;0o|3hXF*B^YsnTlHsSg>%sL90erHp&x*zlT5Z-tB%H8w8@ zM;*2^ENxX%bsi=)xZwEVl3|4LBDLno{;&%xCdmx5YU8{=Ju3ny3(!R2#IDrE#ieES z6byXWa#O&SojE=}{%&F6&Iq?}Oehi>2#?;uN;5Y_qZuwQaJS+Z{rPeKX5JuMP}>Yt z`k?!qLz@nOiI6g2cf0u~;^^=&%jlUJR&V9x9i-3 z_pMJ^w=iW2rEYyQuD)NO*|j&8m$~yZ&IEUcN!Ncf#!E7#>-;kOyY;RQ-~9y+$iW!@ zgy-#avVvY379)B)AcWf3F?|=Pz9?58K>2}hvw9{)qhr3%WYPl}w;F@L{3%Vb zOp5&}58t0M!sd5&A@d$U2$ny4qL9&XWuXtr);4nZ*Q z&GV$bT%)?538wmi)A0J!+8sDiym$NOAMJCUAKLV7EKSFznd)5xn8vIi z?GDC3VNY2JrlZg31!E|09mf{CtT^n27?y0#9u6q{BltpOD+X3e75L_B!1e8Z_eCRJ>orYQJ%e!G|j} zWj+F*Qzsx^Ru!r=-c&|^!#WSI<9H+IrK+O424LV)UH2IF47h9G2~6`+iQ9^|?x4*KM*R z$INsXrUO?1pq-(sqvI85kOqe7DG7FoNRBUVO`N@6`>w|2o`(;Q?akS;AjZiHoCNdc zsxGI_uhfi@oSgBQe%-3BcAGb@Z0w&YRnDFt`s9Vl82fdQO3nz=IJC^xNw1j*#EE-e z^9Sgo-UKqfki{5VD=&U_#m)~!05VTWaE{=|7(HAT;SI!Ax2})l0<8g|D7yIGkIMe; zBL6NS0JHUEx<+h`8#qL}aw0&|sv0v=s1&yLW9^hE%EkoPuY(26vYr`JrDj*FRG4?v z9R2oL{y0pVIMVhiz1K?dh}jCOY2{9=4eGZuQz*0MF*cW#URp|&OvA#QPLkCU@vi=i zcZE+3!QTw;7b;a~q)Iq+aZDMeFZ(X+Sl$ld)+mLKk5ZJ!*Y`o|GJ@Zv2v4cvd6WqP za*iIS3uS0NM~Bj6I>mWpbdr~V)IN}I2Db`8X%H?t=U00WS&yt7o z-8j&s??sXFAEgmBH0OJ-7Bi+kELZF8yKLm8{U&vK>weeJ@BDXX?Ol@074fEuCf6R) zzk5aprp=lU>o&H!eGmJAN`v=+Bx2;EXI5O8u*u5OErRK0kZhFGu%<6pigY{fjAlt1 zEPdB6U3%tS+%XV!(8^zHiz^Ts`y-+jkB&$n8LJinU=l1)lR?L6uR^`Szj+?_+dhv@ z@a6+ZgGeJ&1Q|wz1hNan5R67=YPk4@Zmng-Zwdy|TaqxDAHH#%7@od_`T2>wucY1< z0VJl6KPniPE@P>l&g0ELAxcV?ARQhWkC}WoH~&AZy=7EYVHY)eC<&Diq>=9K5TzR= zq`SLOK#)EP(jX}yUD6HGA|WXqil7Kct91G;-gmrr-23DHy7&B22AsY3v!7?Jx#o&l z(r7Uy*@s_BLtp=y{3(a9Jxg9h6L%3tcc}5>b#WXc{8)dcY-jJOI{662JLyH2ZhBwa znp{LEdA=<@H!5ZR<~BXamAM{EW$d+c+h}q8YIicF{_E9Y)a5-HMNJY{F`sYYdrN^% zgORj+MusFDCv$lVk6$rlObsQI$K43$Qy)y<0~W?P9KvLK)~q z64R(}{KbnvBp?`3P|#TA$9yt*)=GJ8f_{AcqBiBPl`=P*t*d*G)n3||8?9m$hVA5L zX2@HIWW7U%f_1CAg1>2$A!MmHbqtIDC3IWZRGtbxR7f0KW}fmx(YWLA`0Gtn+w^}^}%YKF7wjrh#ZGVXU?IKON6*cxD<3#Ab%)z6sD(~v8T z^NYi0_P(HE)NxRG6Kjpds^aPx$1jTt;ny1;3>nogc~*1vNNsErI-}Zf6yYi?Qb~=q zSv^6_ujF-6k68PvqUNl(njPoS;N6M!bCe!-%f-C}FYSfw7` z`_$Cuf2!_ra8`&^9aX+&Z@Q%t=h5|cD?ecGS_cv0fZnMDWdU-@wh;Z8XXz3^>;~j!57tUb%}v|2|;PEm|~~ zFWrNtRhuYQ;r&n%<>f52gDhuK8f8DbvyYCzZ^k7|*du*SEz=mo>u*)*_4MgBReipa zzrkm&!;Qqhfz0HS_)Mv~JddVy{1$h=B{>#-6}5ETd-PsFUh;nH<1p+De*8NxUpF!` zAT}u%#a1GM@el01-nBt{fk-JM{5zH=JBqvfuvE(ac_O>^+J@=FgR;*UW=Z*xEI)Q) z=(_#rtEqCGp0C{Wue?~2@DFXM3**k#Zn4onOMDQMJU$asY<8MTb@lz*(X@)))sYj) z-CA}GStg}Kwoz1(gF$nGexBL}-<6?V+?IAf8n4c;X#wAUqsETkA5easCEu5|Ym(=K zM}E&~@3Cje?PjT(z+yLQn&2cFXS!F>`NG2=1efRfK6usl71B6A!Hkhx561t6{m9`p z>cE!*oV3@T-Rc~L{uR&js`+bZq=V}@-R3@@Dl2H+IW_%u-mRmvXPo3#ChmupDDZ;D zG6K!R-%fqvGbz6FhVp?tXG}i*uVr&F7ZsiJU)J3GzoC)xrzKWw0U>)BSZc@sx75>W z5PU9V7}a<2RTjnZB+JD)?dg(Vq5XZh9Y7#Q^rulW!MxoSi}q>Ep3~O9GrX(iKgpvv z_k7(Z&GMF`4h6=x=Py-1ZTQ?{@wwmbq&M2K%D#u|YqBzzj4Gp>85`$Q@_Cn1hJ38X z(?RPrX;gZLxxb~ZYJBl?dymqolE_R7rqo9q@S)qKxl7`UMg*T#+Qm?|e?9V+Qi^>g@5PrSgTI_+e(~9sZyz6xVNK8 z;(<)Ko6T}JA>p2`R`^?*65NknlD&TPLx-xYz6MM;x)22oPV^#7^F(fvme?tN_E%v&hgUyFMamx6LjkQ5~t<+S=imLxs!$4u=wM#<45{SVP zt)GG%N#j*V?a(XZt}LJcFrno=~e-bE@ICCuW{6k7b9%@6XW z>Uu#BS{O@0hp42Ywl3KOl~;z-hRHE_&K~B=pM16Vke*RWP`e9TARG;z-!RwkO#JWX zu-U7>)R-^zS(g2SCM)3$5_!w>rZ~xH zfjyc?0f87zJT}gHcIJJM92zglcR7~vY1CegUH14<@s7>s#iUpFcQT}K5^+VCM1^=> za#7#ZMTytt*UR?0fk;T&Wn4d2c>Ja)nM2%VQ%bF5aY%uJGVvkN+pJoe@8(xi&QPN=8XQE z`WC^eXeEhGZufv-znz_p%hc4PWIS#>Pu?flB1A;LKK=RxC}6|mzo98a?|RVc6Sxz! z8zaJaM}}EfeCp2TbB~k7+ZF25Z;z|~eQEEzw>x{A3O{^hWB$;_j@yX|HL&g2L2Q(F zQ+4pcfRhB_^QU|dp#$ynEvGL%=_GsdL1e+6W*!Hrwr@|{pZ}D%rfj~U3e8O8!^)eI zVjLO{!xAcjdz0%~uioIQvJXqe2gqoxI8xyfc!lL^D*Fs9w0|J|Ev;#19J;Da)@VXs zG$3RdYG;&BrtC7FJ)}D4SY5HmzQM#YB9sv)^>?uF(!%svl!?b zVy$jHYrD-~C|E=rF2)-UDTL*g7PHHZk2}V)k5An&eVzm!DI62zBnjm6J=ss4!ECFP zIp|=q6r=5Yn`EVFC0km9hg8!-@D&HtMIYwc>KjofezI78zwLGx4HL%QsI74i^(mJ& zr9e*kE3=vOhqdqIfVFy7BxoQ zk1>q&Lz76Bh&{a&q;vu|JE}+{l&YJ!lX(j1Y*S=xQxrmSEe7(*GHKsUsRhY( zLH%dKzEc3dvN7A{6Ys)f9d1;Gi5Dt^>}Y3R{+J0Yl(&L@{&Y+o{VRG~|3L2gSoD)a z3ClDsa_Z^ToL6hm`7Eca+q}|Uicz<@YF0lfV`T*(aOWhw9&cD@}T0b*;~| zb7hsJ(TUua%J;*)i}VULyhWjI{Bc=|Chy7c!XFlQs)Bl-tJi$I(oFdQd^6!}a<4rk zWh?jJW0bU_q*LzZJh^2YNP}WrtQc4G*K$d2=?xF%;7b;pFB-&YBRV^82Za^nyOK~Y z@b3_1;NLEUT!iA_IO!dYiNrDL2-bD2z65Tn==+HXNyT4rMuYybh-liLa?G!vt8=Gz z#>o(hc{aC0_&RYBDe=rxCv2!U2$VvreFi^SPkqq&tj*0XOMnRN!;jD%!{x539*H*4 zHMzgw&=Nrh*kVo=Tqln9{Ib>9&e=!dz;uEuvhLl6r*W>aX85l;jXyTqq8pRb;n1Sp zqhJ0czd_VcmVbK?M=@XG7nURjl@*RGYrj_Q>-Ie|$%2!d1}ijoDx?*)Z^$q@enL9K z7j&Ab2fx^*MkG_myfziORx#KiD-)I~81G(BrlP&`cCtnAYD+y*QP?w#@^M+_s==`w z{;2&W4U_=Lx;!8HZd~VwzKr$qWrV1cc6aHj;@Q9X`}-#>kx+v8ZnuT+^*IgF_$M7L zZFf9I4=Z~75Mdh$!T7YCco550NKQ2low+`-em+(t4NOhK!b07m!y3qPXQKVt!LPKo zTX}Y=SwO{vi6xb(v84X+bofA9Z@TPVrQhYIPI4{ouIh`znVOmz zsYJgZ$|7o}JiPH}R9`XZ{R~~4sE=YoRj$^HCr!kXl+rGH{gOU8Wuf9-bKo3*{N;jj zN(AXb&(@#hBSHzfn70eVn?DmoXhQFxVhOhp(&hv&3(HZ8wxs;KA&oHi%wdaSaM~uy z`NsCouhNtVAHg^O)9faB64jk|6jbt241_t6hGASBZ*KCGT-<(lbBzvV@$0k-r=|Bp z4?`r$7xGB0-_vIAWoRn)2HcbHX*O>l$WZd5o~VIRn}BovhnI|mLDGVLk@BAi_j&HsC@e3Ma^g}*&E8i1Ht%~kNrmppUa{$ z3<$2TPE0CRFy7WVT9F7Yq3iQ(5y{X(l`UEmW1C08R?P3e_bq9_a^07ggDm0}TLqJi z0D`7M>XwS@eSTGfW}b1(lTcF`tj(`#Us@;xE^*u~Qqf6#=%l$RldL@kL>X;S%y<;2 zxSTnvn)r`@hdMgRwP#6FAqJA(xYU|lji9fV5~O+Dq)ocBHa~wJO0WGShpX{5CPKuT z{AcOrk1`l{twob$T3sdT?+R8p4Cl|<_3V%QfB1nAi{qOGCq8A`EKE&`uAbC4j;|U}u-Qr(6u3lD z*s|!4NwiE5p^9pPo-VwKu}hYHs1xTnA(}MvFLq@<4hY0kDLQE|<6_X!$K*@`Lci)?dtEvdC~x>#WIEQB^Oup*+J7KPdf4R zL=oDQmimsZ0rQ=J9GWDRN#|E9$qf2*w ztqXFT+-!G~-FYTpq5nMF?w{JL=%ijVVN{amZ|B}r4kf)orByRkLM+#pHSY_dbCirQ zWJ#drkz2R!3>-U4Wox@fOr;=*BT7>iR3&W~-X)Au;LC^7^c_r}KFv$apJL|a$;*&J z!|l{h4kFb^$8kIvq1u%8wlU}%cy>vCCuzPfs@_^#->OXTzHBr~$vEB4P?g=A*S(Kw zRaEcfB2iI!=56ZKQdkke5ed34=F2Iimn#SfLm!|=V+9B2m_;`kengn3+NWhReN-4Z zGQc+yrs1s^+F+N%O5fIItW9jEArhAI5TP8+rmQqaG1kAQK5|&N)GpDdW$K<&Glusf zj7oO)zI$s`ko$&#r-Hsqr=9Q}>EAI$CZgOQTL<InL zQ-W2d`b|}Tjcu$X6Z#h&vb4}b5H$FoUx<%K&79msMNFkLu4OLTzs7s(W}P8TE2$7g z&c3;WDo>P?_s!JB6W>!xNIFEL5s&$=#>yj8sC-BLJ%wE(^`6I!6ESBqAt*^gRnl6` zho5g=MXajP8KR$H@`NiUiX^EHPZUEEi`A|Z#&hHLn=IoHBM^*th_(9z&zf4=mLps~ zABx!?pz>ps%K`* z6Vjg+_x(I+$O&;lpSDk~Q&Dxs^i20iO8NG`S^$lFxkgbg77;pm^1FBbyigO%M}3;r zHU%b7C#u=4zUha`TS`as6gFuo&c=mX5&Pc7J}f(a#?;zBP>$vo0tco8R|4JsRoj@bKMHYH|5+P?eeS80c# z5hL=?ruM0QU&<5ChhR(}j_y%o&<58$uxov`FYWwWL5y2cpG(x@+ndr2(S<-yl8Ild zwfvqN*pWOU&IOf8cQB<rA2gDb4z83SOeHyd=wA zo=vi~(rvz8<9x%EZ}S%g&R#D9zub)UBqRc-?atL3Q)W&eo$Nx)qq|C?)7~-YNSwEF zyPtaVC|%ZGjq!;J1tqy~v>J`+-o;gd2BMmJDN^<}7Tv&|;OI6~DrTPr+@PD@gpBCe zbQ9+mVG;;?*Y|2zv4yx4N7%YP6tXs$M>rqehE&K0S;(+5_vbB*YP<3q5lzt@Y23t3 z_qFFq2ywB)H`f^H;K#vNnpCRgoc@@H}c4?4Xj)W{}T3P+9!nrU+me&i>h zpeN5UYG(21W5r^G-#tf05R^(5qzJD+5mXj+;5xxEqIw+e7W;Q0V8-4HKboM>yk;n@ z6{AM9BkGQ`*tgve?IhI5aHCoYkC9ifWFkAgF(u}okT|55KL0jI*2_67N(j+atwS-M z+PQtn`5lm)lBBU2v=^mvo8Zsv{o+|dTAD;sb)pIQ6X)46j`(WwQ5m2-y# zlrOn>P^D=fES#TO{JsiO(Izdw^Q=VucXPdDItwOoNFDcSOg&4;^>u^jTtzUVv?B5K zU1CLtI@np>;r!lDvZgb4^t5lqq||+NwKy1iakz+gi{Ou}r@3Yu!45eVnug1nOrups z;l4tA2@0J>6;00rx3H2M2B=6bUpih+oLqJxkDTNeSi758iAny8UHg;IX|`dQ6hGsc8b&sXJ*IO{^=cur6Z;MLcXSR)0ZzP z8wpUA6T+L0m!QGigkJBb2o>p6s40f2VaNnUT_Tv0@crU7 z`1-k-xkQG?b`o|u=&x=V88EX5+@YC~NAh5_#Q2JdkUZg_UX1Vj=Ur2{e_nYLD@3+b zRf;ZY!{~Zre7`7dt|8)3X6F6|t`Qpa$FHD5+ z=Sn@!4+12;dQ>fMJ-q^?)Pnx|1=uYiL>wTs5;4zIWqA61eDW?I4lU6T(o%M~_I=r< zBiTC;=k;B|h=LR4-aYP!0a{=C03F8T{(!)us}wP>e3k*>;|;HMDjynTLIk%1 z-paKXysos*DWkn zYJD{XyGAj%Va_*bd;MX(<8XXQPP6|LLtfDqW`V5I2}^C)5U;C6y~rVjgd{cvZy#CX zk3SQ=5w7(L$sQ}(PT{FZ-#PXUM~50#9nqiQVMMi>c9n7JmJ)+sK|0)L_Vo z71}!FDar#w)&!+X(1wO&AD3$9v3#RRtYv=RqvE$B{tn?T^WYs@@;fV)LG#=CM2j*n zn#pA~+lE)4aDM&LVbD@!9!(&P8y==afsY@bmBp!)XjtJo{$ko+A-Ot1@uLFR2-YW?0C11+qZq2Kc%;Kc7|%?HiCOPuRk$hh3b~=bS3gx z8wjPV#>B)>8L1*@kf6#{U0u!IJPRAkAjQT&w^V!B+D?Gn%F+^D%6=r2c?c=e;29lE zlNI~(+t)??}t$op==$V;VuOeNF(u~6{^870HdijJoE*AUeejg z2@;8%nx4i$M@Mx1yE^WSh`^GBU~MjiEhBt?;oJK-@?$BXLS&3*hB0W+En9zSrA z-c!g9#H+qKQv^9~*naCbB-2E_)(%H|Y@}FqO0{92vQd+(nu^NM=;+nO{#bt;H8l~@ z)bkG%w6a)-M^hLlepk)MvL@~G){XG*vB1AYpW@UI1x2#E=8f#vcE??0Hk3UBTW;5~ z(WdM!IXU^m%Y#Yin}fG;b$JfjCR8rlVRBf#q~KaFpZ|_#!IGIEM7>T2t0XC_Mf|#K`q z=i%{?tyvq!@cou|R7(1CTe@WD^JC!$_AkWgE>>N^`RaleUzU6jTXc7B6Y(P)}ZH>!_~QD4PcP8qBYqE4HVgt9IYx2ePWl4HSsx4;K~| z`0YlqLg7@QqM}+_T8h0axPALJCf+?+tlqvp&`UEQ*z5{HgVWL7-3@}#;M4VP5)OWM zzW@!QS`GzSSy_2`HnsP8dD293;XMQtAYKBa$EF9(wTOs`b#--%3JR(TH=)7on)(^? zgiA?^2`FNUw{5xFmUQ^Q=X+qJ3lXu-+uqL{UXaKDhwdL22Zyt>Gsv1A92`VPMaf`s8Z~b3k4cPu`ZQl- zr2tCx`ub@`67Oy?)%IFGJ6%n^7T9r|Vu_K5nLmep6mCh$$@&RYm*b=VEM+Rp}GT64AQXIGt7^JNE=EUVi7;vfcUhwrV$(iZ)F^!&%iSD5#F z&BycPw#E8KS1-xYwOI0KTIK(5*r(vjMq{&FtFqAYnDi8 z589Zi$Y4+^4>TDS@!?Lxf>+Q6*L@;p;^?@!Jzq!dyNm**gz&mR@=lPEvDdNT;qNZA zYq>vohJF6UMU1tKi3X=x;ic!3OG`mN2NKjD98S&G*|k31vaQj-_v~jvjaC0(?J#QV zA0Pz5lox zSM7Si({$VEGx&9ihtEaog05dqp%yD=M_34cBEu(p0YeVrrocrv+}9xXx;}50tp7KLc-EtIWM#j_gbCtxO z>+5zrq;qn}_<3g-wI+jw9r~GfbIP2DX9owdxwS=4M~7Gj9oy~cGLj6zt?~S810y5T z^K``ae$Kdknl}alYNH43lv(|?F{FNx#<5L`*4EWQ!G1U%wW*$7Khpp%l~_S^wam*~ z-K4Glc*6o$aB`sH^!kl}WsBr`ib3xj-eArPCW#6c(?4u`roza=!a`G1Q&tw4(IM0j zVpze&#^!hNr~iStI3FLMYv-l6Pd0~F$Z0^vh^-vm(e!usYD^khT3UEnjg5_HzT!L- z$trp;@ZUV}Z|pW#R91cu`!6pq@2iO_!hEoXB@!BcHsN5yqL9bvmg$HRunP%!ua9Qs zE5z;cBvu;KF^P+d!%;^Z_+5h1Vh32Q<>h7AbRdN~ySSCKDj_WF)ARB+4Cu10dj|Fb zVJ?(mfI!9<7Z=Ot&x4U!^jR7yBCm8xslxA7vzvaWBcETBlVkp^?b+}s+t9V&0ij@! zq}%QMcLig0nksdBZ?0Y*FJ%ij-0>$gPg7;GL8>V#>epH;0W^RqNJc|Z_=au1e_Wat z*Vfn9-9^$0Kstb%d(SQCJR>~3zuKb5wRJ}*tQ(O^4jwTS#GJNnl5labvZf2UylKsFH0dI3s)>x(VvDrwk0+u1$-#Plu^fgMOD?EfsI>z= z>+E0yx-AY54xVhq-a@2}*1!$}Gs$gGE87zL*=@^>t3Ul<49_Y1^z;|J0F?S4 zSo|Qp^%C4I2?(ygo&piH#?47nbzf@Ki9^_O1VJi%M*@ zt1+=lkDr~Jo0}~*&9x{VItIpzmoMMD$+)2*HK1sGw$g;2o}T$prtigxhr3r$>>3!! zqGA0PwMB8fDK_a^e%o_3l_sr#3%n5xiCTk5RD?~+=cOeHfB=wK`5sPPltfHKB;rK7 zi#1sZ2Co5pnn9gy4Wpu|si{~N?whk+sKySwJd>Iv+$pNADbCBYgk8ejexT*-%)zg< zd3Xlj|1v!M7!>b{GF%s$+^Cyd3T^?CC@3g^E!hE{KRfWO^piEL>1)eU7?dDP9s_0f z7{`10V00}lf0StEuZ?Db^_&54L4!m^Lz~YRbC_Vr7|}H}+?iD~?e<%oqUQ4O`pq`E&6Md&NhOijwY$`)UyNLQC9Ae_a2^kHHx#IEdBN)oW#A zkmCGwAZOdD$utT&FCHEq#>SM*bp^Mi6|Jo3&yBUUKYqi%fp>4XameC^ic(@*Tbr09 zW}$Cla&j{CeXI$WioXM3u2(j_+YxYU=(OHp@}A$X-0m>U;=)3U=<~y^ej!Rtzh&yc z6Iu?A;ecKw(~Au_pI?4{dJPcnYiCdpQUmns;W+nNYKBrheBSIdTj@?lU+z!g@Fh5T zDxOvb97~=1cj>zM%#4il-PS$two8h;$35`wPBd~HARZ`}5jsURea}Z~Y2$^>UcV4V=)5}K> z3=VFN=l6quy>W~5bA^#`Q=s$wts!s|u!2v1FL%Rs{A62KSWsYXZOviU(bm!NZFW|e zo12@9%k^5Rk(1T`4DJgg0`E{!RZKg^-FtBMD?bjldPGD72*8u^+k#)-TWD~CEe#JB zKv8XJ61YDi4DH94mzQ;Qb^S3EB;amMOxocwmY2;NDNnxn?;Rc=!}O)Qu+!j!=<4t9 zx2-$em{h<=Mn^|CEd}}mo`F$0u(9DOpB~>MMTCZi&TW+~x;E)^fVMS6hKpdk0e27* z5NJZ&r=h{)vLMhLO)wL)laeayF#^%qjo@Fu?2kr&?oKa}GpoO~HuQ$um(|=hPXq=L(<&15+>VZiVqy!kvrX{4 z<>j{!A3l5#>*C6f28~h}<-E295y172o^F1uOifPSIE1j%*C#b;wG%caw8q=k@hXLZ zKwD1_OzMWvVMyFC?MrKG50Vp35H~k762bs6ZZWWoHToP`Voz~y-){dV+HRPp0X_?i zB{CiyT6{cyks_#>!%#g9Ws{FSPH9!b2v8M;djJ$<`vO3OsHiAb?%bR{sEnc@br>Ls z2XG-Epq)RC=z2xSyzPA-!NAO1$0(ATR8P;YKeB;%8kGK(Ch>j5voOWmRF?$_6vg+l zHcFnp8(6JnC|uF;h!ULBEKBz2IqFJfb?DctCUQx7=4-sSZ7f5yR2$3Y5T#J!J#eOj zwB#9grBuqQ@=5D1-4T0%%fM>9S-p-sADs1KGd}Je|EQr=Kk zf&!uca7Vc7>Zp3v|Dk%myDyMcnnMohIvlO%H}3xNUkb>#KS6BxesndDtWaW|GJs|-)}QLJ**Dv3DUc7!*^qaq^r(n84SqksJ0eQ5xpBta38agYep1J zd$#?<&eaeuVcdjr72D>cBRodzvgtR;$%25Q;ly9^7Gb0yd%joCJMWP0{9PTItun() z)dNjk@2~6AJ&E*44ue|j$s)DS*2IogCq^oNz`H@y8fa5ml4uf+^jJk_3D006>gG9= z?jS($4|K`b!CZ6vgrlWbXB`=u|e}lIDz6;(Bd4YBnD}S*-51Q2#1RdSRht=Ev|G74eF3 z%Ns!T2)Qf};p3b0rKgqVHw^zXMKKyeyWf2Ii8m zF8#Y)3dOjYGfx`yX(}sff$=wVeBx3+9DdmO`@>BT9OwG;@0+yK`PtdwR#a3Jm;w|U z0Ahnltp6_7C7c``-!zp0w0!hd{24q?`EPaD_)7uDymyO>iq-&faj~*md_Ufv-=9>M zs2Ky9_MnZz)SUG1jWKK;)&Z<|LkiRZ3`2ZPB_3ZfuD8o95--?RPpUSVA z%H=-c5+IpIzHkW43c;_{=KxLvjNkpJNozis)o=ww0m!z-B(i&7NAut%_W%A3ygIe> zZtd(0%6=GdZ9652Ie}EdCU#ksn4IgrZ|q+Dc)j8#WQ@e=BrVnmOIp3TL6kN>OIv> zH@rXA>={str4^!+IgMa*d#2Ntch(Zi`p<@5wyP6sTMA{SO zT-H*NGA52_6TdBX*MzA0MBD zq+iu0Rp1${_>GTSStz*0R+d5;5I(!{km^>MWPta4@cLyz}MwPe1kS)YQTDycgJjw{PEK z9M?gpH zM&R|3t^oc0{{4FhtR+sC!(dJHTfJc#Oxx*N2CU?8{Wm};fb2%z2yOwszSt{0)>HH9+Gd;>=QA%WqgeBbT{1@oz>Z+)y2y_cTzx>IKa@{QuK#!vo z)iN>3N=iC7?)>+Fh6ct@;q{gxrLbJ)q$@D&T)=TgV;JI7`$U&Fd;0V^s76Lh!g?fN9Gq)76a`7IX?@3-kqqk?CeCGBPp_4jW(qIf;joSRXe!&nKp* zp8^R}s{L*jnlZ26IfTP7fE#+6QGyLx*2c1zs?0hecD#=0A(U2CR{nc<=;G}Be5YY{ z*mfU$D=;$G4s8>fq7P?`U{3dka2{?zLlb+t|B?DzZ*zmaFR=|M?Ww^lO04r2hUjBTuv>09n1UWqN-{eED=f$_}!8cdmvU+%jW9r)Pc7K z-U)1oiTEdIVxF^;!XM3+_&1@#{Q`-+{tMXm5Og>|Yz6b7!PA>+YVtZv6m)fUL2P)I ztY?~j->0&wYA;UW>I94i00Tifx*tHK10b9?{unI@;3qmF0;J`KIl}R44J$xN9$dyU zyrc7jjh=UZ;aA~2J_ln)%xzk3UG@I`8Js-0YX~A;NaJyEaON09`h39v!ltI?wfuN} z6MA~b;|kPj;8Q;(GJ?diYZE~E3e)!Y9UXxa1xld527Blh4i5PPzxqX2vqonKXcl2G z4PM>+^Roj7d(S=y6yCiXw5@Y!Fm(O+C>=uA{|kq#sSjf8Blz{{8@rMb#_`3CYrvNj2Db znO<*m9h9Ab3%jPgz!TsiU`62WxZ8ez088u%QClaNS+K4?@cv-?4!J(jtp<7xXu?zu zgAW|+a6lmBe=F!joRKc(`E#HzhGOsi7MCUwgwYmRkNS5bMjEBs;Ksy#c8!&kKHcAIBc!CvOiTpa)A=0y z99W~Gq>jIX?1RXn&Q1yb%=#j8i)h%9qnV=n9|_f;Yykt=hK|rAf)o}1$41~wZDZ6@ zREX4JttlV=0X@aGH~8y(|+KNV2L4UMw0|h zb%BQKoP}D3kjHf73YR-I2kyFI_wbFLaJ=Kce+@eW+oQa=_I*6=ab|Wd>>L#oFesPy zeE+=hMpRa0E*%K!$vf! zm@#SfmU{ho6i7@g+Up~keS=o}zsZrbv;j&RELvF68G8W?42-0SH*d&oFXC;|4eBy$ z=AGf7Vq;;M3qyQd07@+d1#`|q*IAFqdHLc=O=XD9--G`ID?m>B@j%5Or9YaC@Xj4R zt3L3ZKrpUvH|L+k8&u3d3NKmNrooW4@J5&gECr<3yj!!LePn+&>DT}k7)&2*ic2sa z^TSq7I`UW>6NN)rKHpm0zkdKGlkXo->Qs7KLP7%U6jd%@=V0|9Zq684OB8Em2PJF# z52)ec;c#+*bx*v#egbZn`tIG{a<%e#Ea)oOGtGMBv)qNEn+qVITAyQ>a|1|9$j$&F z5f3f4xP|Jy?8rqnrU}CNlxE zzrM2aIy-wzx^|OLE+ILMC2}|ww(2#`0GM?JhX_W^Wzp+>-4vy43O1@1$#lZVnEicl z(6;{8AL2JK)(?xcSURO&V|Ux|gfU@+wuIN2&5IPADCS0`b{kdb5{nvz^xmQkrAZrE zyEYZr#MIOho<9}s$qlG*!z~*;m8cNTLKGRPD2S{_z}I}5;`V+KVE-_M9+}q1goWBS z_uZXG!nN1PKvMwXxus|8RE)H%VnaclftOd8dqHvJf`cIHs`APBj#fR{8rImv)1!X7 z?pR9ETB!Q2&~<7s#HNL+hM2`+0%^yFvzGO@@QxNCIs`Mn0_0{AZAS8n*x-Vy-stG}t8EO!G0t6vZ)i$g+fbjQqL zLittAjEKjNk3jndK$7V?@d=&*KmvvoK045vyFR@h^#2K(jI0griF*D7Cl2T*U$-pF zMH`W$TQ*PQ$U|y4<(Y&xlKN7#r>HCKl_EB)Qets2^Ot8s7>uLDR#q}p6gyCSAeV3| zahqJ=m#3_^0UH*A)XFaFr2~Uo+aGzbIqB(x_5u&##dB0E7Y+^$eF5eYKx`w>&XD1S z!)W$MnoI6uB&3Zk!MF@=HUj+Puc{K_8}sx9j0>m84@|t%OgR~(q>S#*H>Oo2GaE$& zzY(IcZ)Hoy5+uLP&SKB^O+#6bd<3Q<7`8D&Mg@pPaGII0gTba>!`X$fJHdi2#FOL? zpP#^wV57Ezv4CL~g(e52Hf35fNLfvBNZoNZef^Q?>VzFbF31M<4h%A&+N;mGGT^#U zataD$4J-z~gExGPq#P9tVHHD2VvRdCT%(*INDut@VcAQ@!o&nP{~F-T&Nn!v?q?Fz zMG3@JoK~?V4_fna8q^|9APFn_bdzWj`SLb}txyKgipdlswq7zaXae)uZ{l<~_;Yh} z!M-|&do&ov@P30)K;hvE|E?|#NK?04J}!%wut&bxuX4^00r-1O3OZR>IzFKz$qX2KAD*AX>j*~b+MLO~cB)#A>oQsKozskgL)5Omh>GSRbVb->t#xHZ* z$tuf@kA1k%l}jHL8?|`aJbl^#xubb!Fbj$hftO8tx0(?360fMLt4l!Tz_`6N3WS<- ziK@~AQ0I}1EZ1fK(w|#d8Ef(?E>0cNiLF(vJiVj65{oUjkuP5s6&8+UOLW%O{yqBQ z=En8H%RIGjh4PlwFcV#STbtj(ubQV@y7rFJ3UT)!QYIrK`>aK%MVG+vN>DRK-U|RE z*{vHkLKl!qFEDli>Z+DunNC^{W|{U?*{J>eAf5> ze1 zghc=T#04F|rh&)<02?H-o*m8GLCKaw-8{tFNx4I0Mg7+dIPkn+kHj-_??3tV84XXo zYvvYeu*y-UgR`>$dCZ_*RPP4?#LG|CfS93h4s3y0XP{ZYVX|@|8_*~LXZ5;e6;&{R z3_QnOV&X>`LNQum79Ws*R{FV3+fIN^uy9?7Tm~w66juvMF-G&*VcvNEAIy!|~rAhJf`I;W};YD|oob@6g{(*8P@JC{x>mX+%Kpyb?c@jmI-BUHD z*IpqaB&dbjgm3WQ*}gwsfg^$-6JS6L01Jr0TD^D9AcwZARgAzV zB&>6o1ajkJqtH_kN>xs1MF0Zr3W7U8YFir{pN?L+r${F<6n0mSDTl$33XOOAEf`kM zXH9(CA;^Hdd=gMG86{NWzC1?g%XA{G2{uK!x!=JOM*(A`s(KCiWi_>(!;$fTi&(#? z)=!;@WJ(Zx0Q6ktb5A5Q_Qw7S6bu-do6}Gz@b=Zz)IgdELiWG=`&P=TQ0q}|Sdp4K z3#lY=j~}vO-S|{gR76Bb-Xl0K8$}sOUqGT7az94*U*bT~WvT?VA( zAOwIwk@>A}sEfB8tD3qx-p!jftc$nuT>upiNCt~7#IyDsEIVimeYi{0EI8tA>dp}a(RRRxf&Gl zSX(oQjOafD9sUZvmdMvrv?&9u>exibaz|8%j3bK3VSk%l~FR4c> zGtNbmtC2KgziOL{k&Srb*@?v$VG-sjOIu@e@A5U_#*W2Y%yqmZVS|p9bpIw_;6=w}IM~0RPB@N3z z6SJ#e2jeTNt1mTsKiQmMc%zq6`%9HgRdTi|9!#EIdT3@c2$bw_YAXr zdZ{N_RAWZ1y{E-Op)D7ii5e6M^#PZEAM1HfA`q~lq1N~0^pv;%x6t2t?|pmDibk~i zn22CVEV4sF)U}C!tWHQ7+pwx!XrV&o8&@ZG0|EBA-w}*2OM(W9wz$h%Ajog*QLP11V#U&>d z#^S#>eX77(m~_?sqfR!tYF6$!BVJI!HdiQrrQUb5RH2{%isw#lZ)ckb?K$;kS05OJ z;7_zkR{96^wh%){EJn0Ey+1D@vhqRbb#)vu3g$1kW11{xF zYUdEIjR!{Cqaw2r6pi&+82`d3#A!c1GrwB7{f$%i>~II&a7c$@_8-FV`Noe+9n6<{ zKiw1)(Gl4JM+RUj+}+)wq!3_0v04Vy7ew;fcEVu>z9t)k38|s1M2J|vFz9Bym4Dhk zD#1&Mi-~v+Bg`Oja_OJ(M(&{IO0pOi35|+H0dCBM3LYvkUFDEFIY0Sc+l8sQy6%FL zV`FEps%^@9WPHVmfJEt|?1wH5hE+_5Ox@UBj9PZDW@cxBbP*H2{v01{OakC?|C4mQ zrBKe z5~|GkchVhYEXLFnsyBm_w2(;i0eU99C*-qEyHH)x=-KNbZ0;exzGhHoYHOo>^DgYc zVJ!#T!P#{(KY5LA^D8M=7Q0*=xF=rnnB@a3p2I?*xZb}fuRIvn(4tkl`}F@*b>8t* z|L^~Q$>Lq{Qml# z|8mpqcD!EC=k>g<$K!rIFR{f8dK|x$->ex8<{_Ig;b9*38OWpr_OCKT zJ0@T%q7?|#P!|>jZQ|fq3NKomMT0toW+#?L9hMJH?l>~+I|JAYr z=gLCAxRDxSrE}@^RzpLD9#%(Du^SYXJNo*p1Fr_{GNm2|faX=rwae*$!JwxEtaC^@ zg3asgDV)R%?q2_6ZKXQnrjR@WtaFy+L%r&W`?#k{OR>CfCaW!^uT3j>r$bccLcl%FgB?N0Ld40U+Cma$kq!(`wH}-vFQ4dAL-r_pzE}F76JOmHGpDl zo2}9-gKE`Ve0KBRcBW0s52tIPQ>T#eoT1sYOOOJ9^>(~l9UQ^wUFLyTS|x`ar-vQo_MSAq*S|b&xNeTd!uNP!YfBuKkdaX~v1T*^1&rxy ze-9TIZn;v(%pk#hq@wa6<=YcInIB(yq8i6(vv!U^5UMn+EdWyhR`1=QZd$k5)?HBU zNr{Ow;2Pr1$2?T1qJvl0h=o?)>X+|=5qS)>Hz1Lr#FVTmiOf$5yn^AD%-n#VWpK)P zcFe@#8Pu3=Z*9q-$gT*ypZ_1_IV5%HtftoA?6GtP*Xfr-iUE8KV#t*W%NepA5b>_u z{{jjyWSVf!A00gcJ>uIp8~YJYumbYsqt<-`p`=aE!9xIN(T2ZbV4%FT6!3?Qxps-R zIQ}y`$Hk=*g93>G9I#6L!-E5vQNb^hlm6d6P#C4Qx3>ekHfaVP3qZsC{2n0fz2b@j zojWqJae}G;D_d#fD+D@eGSHJCrzpkV$~*2ubwo_I6@MXVznq$cI?I{1@-jqbR6rCi?_mKkd|Lg`AC) zL5hy?eT6<4$7!}kg~La46xn21!epr>ca;5L5JQCGZ9>)JCFJe-IuU?CJ( zYbZHE;Lm_SwrTK(T~5W<&~aeMl7cdW0Q(2Q8m|!;R>89q5ENuDf*cRN9MY*)SX;|4 zC^%{_6d4i0e_=djHz8U0Qejzrfff}3PS@F{L_{sK-FNxhH!ibQAq)oYIj(_vt*>&# zLN!syZSFNBNt>|HUx%GM*|~}3G_2yA@dr8;w&|?v#Hu%}*>#W{Qj?OBor1+DyV&}wGNM2vThB1#{BN0i#1J3FC|k648tr-@D8np+V*AIrbGGfbcr90h2$T7;Bt=;O!N zf4J@q)X@uIguiJ;c<}j};E~F0V3$jZp4v9wL)J$E9hJ zv$IwvPW}`_adph-^dI(MOG{iWxX$*(_d-!v2%x-8z|IHkI_^oitFqPet@Y#X{T;h0 zb?77O@K{Re9P%P^_P6D9>mNPD+Jmbo;-LlI4AEbGQjMvjkj88UhLs#50u`+*>!m37ZKA{Y)1kp6^3L>gHn z92gCf(OfS-xti4NY$zvSbmSBoTo2ZH<@BP^eZybkpbaw&Ko&SMz_Q%htKL<-5=oRH_o(lh$R00{!VHSb_DWe@H*}IgK~XLwli)!l1)~8=H95v zC$A<<)u`){!Q-Qb8e`#YI4o*$2phH>2~)y>yFY~?%qYfEr=+D>L<(O;vG6>_qB&3p z>n*=Kv<5lYtM8R7w8^(R`8zKEiTY+oST1x43)c{UU9X|3d4^!_ND{488y*~P7qiq06(L#uycBPdl|$$ZQ#yX3%Jl3OH2v84qnp-Pibozbzg4UXwIUR8LIpKDcV`>djd3#e)N>9$ zim+&rMtBBCBU3W8H3$md^`AT~!DW?;qs4wPwWMV}(69V#aE4mlwgfLW1RHyQgC>GoEY)pTfAGihs`w>$C2a>lcBn%FGOF z&U`u~ln;|Xm3x)MPJZr@PD}_o`bPTB;(K|7HsNK_mf^D^u(<(H3oWfgS$sQFn8ljW)uYqO)j+C=5h%+asx;jea zu_-#wj^7F|mX^3YINLxcP_Fzpx>k*))GvG1z102Yfbot=GK#&ZqR(aSwNdqiva+(M zADb_=sm?c-e-+dbtx9VH49|U9Oh|x=fCeHc`ii!C#D${77S8Qg>ajPU7m& zEcxl(3Qb91`^a-Xp}H_nr%UCxF}(}f=fj5&t#D*S@{p0Anbz!=3G%y55Si+U_$z{u zgD8m$CKeW(i;HhR@+FUecp(xvV|?GfR)de4pL+k%@gvzi`fPJT)GDdPdHkds?Wu>Yhdl&f(ISiyLdTK@`WSXfQ5Ue4XpM#do4!R|@TqiTl^Aoe=c)Zc&q3RpXIyQeb5l7Q7oMi)%1fus{j&H$Qku-peQe*uNmFK;m9 z$`o-qYqtR?j#4#IgOw6lhl~vDBB(F`jRRwyv*-_aL=cN5f#onZHU?Y-ItYLv06=HH zNS&s6lIQn4q^6K17bgR@3%!K!fpnF|;*oA5Gj1DxJN@@Q_>doSZeK$tCmOBnUMATt z5ACI_33n+{laYih*p&5YS0|!uLyvb~ZpItra*4L#7*L%&NgZS;;@^687KZ1WV9zqj zN6I+4S|uZ0ad+CdPEBI|3pf}oPdkVCce-Kr(Eo0Cs`S16y&UsbQLG8*5jK?&nXVg& zNP&&1Qu^YZu+7jX1@rjQmP%+J#6y;h7VWdZpO?Tk)V%l+E!$N?OH2&66PhFtyh8Vl ztEz0yHaVV@ej8aGta&7*yt!HZZB8wF`d8VV4)K-uwuRZ;Dn0}_v?_BuqRD#b z{RmLHO-ZpoN-`S5RN2|s*f=?%T@>~PcxuGUqW!Jz!0Pn$C;@k!O5t`NPv*!ZZizs4 z5?%`EO$iAIcuv+>(e-9aK7<0m6AV|LwAiKQ1pf0>rRRf;k-e*(s7I2|t5ZTq z@h`VN>Ekn%Ai4RAsOqLf#4R)dpA<2_Ap7NdV;7L5WMxA~SA{Y(z>mj0C3AoHmZ-Yn z-R`G(9(US@chc6!igI0^O;@SzqlENs@>V+sI_zA@y=aN6nv#s4ccKe4xT~q@qNzCu zL^F`3lMYspz&S@8s-1s=n6>NI?fl1zts$3}Vc+nsclZ_%swqyGE%1A$ZbsYm@7%t1 zwBALJx{*|SDshjvb>G7@i=YfRgY?Vs1)81T274VGJvbjkdZ$nEV!Roy(IktkGTVwH z1A|5|A*5C>ZB6#bRHOIkS+EJpm}lZ+{Zo_;j@{7|OmpCFg1H0IA*{09wFxjE&&O64 z((ezS`WJ2dHqy$+uBpdiu+?T|)~VDi1Z?h}5xox52ji4hwZwBY5h$ysSvxvm2mifG zMS3x44mP%Q!3S|O8$8_Hwi69#g5(iE!@a$|`PO<5A*QChwX~#qgF!()2^~QY{kMsq z_t1j13-U9Z3h~*6FfBn_8z7{vpH_E<DhAt~Gi~4sdtz4B$31#n?V#QL?;xovX#N4XwZgF08iWO+@I?S+Afctm_Mi0l zVlVVcuxMrj$kg8x7Qq{{V2juzz-ToOpNM~XaZut*I5f;-O^>t+88!o8W;ufj*r*h+ndzIW6Kwa%YF9m zHIet{jg2>epB3q4q@-NNy|Fe3Z&Tx?IvQec*BT^cuU(;wy8rH7^u!BJ8&l2uhZzH! zZ!YA7;oc41&Z?SVyUt?(>lv6^F#VukHY+!`1FSvdLXIAFpuWYM>Z(6B@%V%Y;!dIy z5jE;s9Cax)jq|EDgWD~SFKx7P3yt9oWxfX=X+WGf<7{_!AgxT-WJ((de|S>MSXog4 zj7pYT(Ql(vfOU+DtgUd{KmtCtOIT`-i;Dv>HQM%wkY9?`^4ifg!VuF>pLT2mkLMYY z6zW@7sBaQjZ8et$Tj4raL-Hwe*8d5!c};PaNBmV65^4+umr?8@K$`Ctn)7WzZq&hsj# zVP`J%b&`;#s73JWvr!>6@bmO^+U2NUJCC18onH^M?07=X-vfm`Fk&#zSt^rG-Mn8- zfIhRG?81eC!9g?VSc5Jhs5DKCjTJ0Ns5A8q4AK%37JS<-lXL?Vl$M-KFdJ~^H9Jg} zZ$Fiqy51WdWOaISa9xZ1?T>%v1JkdIn)CB#uM{s3$cf>mU2@pvZwL@wnPiMlQ9#b+ zi(j4qPsQA178;=%U1zU$-J|9sLVU(M`lB@PHfxIrkUQ$?58moA8~B)oTE+RA-qSSW zx^{~QwW^zge(_mGbWs#6MtJ7+#f=--h}si zx}6>G{o5gvyhSga51}L>x7^z>&S=uWdEU57ctv^Y=Mj=D^XdoMfN|P=%3|-y{nxJ~ z!~Q;!^S8y7vFXLHEo(`iig#o24fb;FW5x$=V?Aj+z3F>IZFM26xoZ3m280#uuc? zgyWc!7wEs@F}}DL89pIuXlg1MbmX6*LH!Z$S>;s2(A?$LCc#VxMo39XNuY!? z>RmpdRztZ%|K<6SVbMu_1PEPk46#$*q3IKTEp2U>ey2Q}AB__tvG=SMxcd00P`zX4 zp<+x3pM{6J=2%PtU%MQJ9w%l}QtsyY^T+x5)i~~r9C9@=bNaMoJcM>5~<|D)PTU7C_78R2Fd-kSYb_~Y&A4n?_xRk_22-TFSrV!V&-b? zB;{y6Y{sSg?1Z?44-f8CE6_UUr>3UDMFNnb!w`!7IY0d_H@d{o%e2m!^;6E^J&qe# zJZ=C{~2f!0Q0hvHB z^lY%SzAi1%a2eLXr75MQrI5~BG`m}YCx229zWVBOGn3Z!t-r5HmwviAO*_-mGo?k* zl0A`*j~!zVucA{!^?E?d5G4GdGDkms8liJufB;d+f0ps<;(_t3zT51s$k)puXdmOt zWv8XBeo|lMDor-Ixuv9}peff-fMd9nEWNh@N*~|0_JV>ib_ux;>HPQQ>cYW3jlaDI z!*`M}C~KJ{`#%Q*=kxM3$&Un%q>vEKT>SGg1PM-ypWM4~obQbbxb@vZjE3V;iqBtg3Sh}Xm#qhC6K*1kR6%yt-ac!|hrvRP?ktiSpU)~ng7{}} z1bsfnTbod3X%d~A(F=}A!)FXrVtBmIwAsy~`9rf@VUvGbZ0ETpkp+sJL_~*zNOSpz z#5rnzr#_sRdZSQ-Z@<45#^xaV_{8Pp-LuHN)x0(zN$aL7>v|~^#&o?P#W{nodUo%C zkUjc~|710Go{JfOfX3M(OUNOycj?){cUV^QKjRp!hIn2adL({VgxyX@JC_==;Z}kXN*^Z5dT|zBbdSp4BjR&v zd_5q0n1KROVN?fHOq(^dhsHs0|Fx&in8zMc<2d5==#-*rRPjH@)OdfDAZ1o}Nwju| z!Yvd9+?+)HK?Fi!$!JDent_=acR(HCx_@--Rbj`wK&Jt1f?|w`iTRkzZmFu@(r06R zGcXdgXot~ac!>)gbVpJnJW?A(Qs(d9-CSP{TZ1Ppp*voCdYaJ!OkwLI47q z0qPHW`vFPQhvp)%H(;C-DkJeJfz}IESbhC-TiF8M>3?4J zvCOdT;9UbY=G9^fuNzuEOkmI(Hp@HMmT*>b6w(6Fpdq&+C6WieTSG&m1}(R}2*bjF z!7?+u&iD=b1RnI+Lyu{v#}`oh%|V$0A{{7-xND+S5XcypS=?<{Sf-=#Mro)gve;jW z|Fz8xy}#MIVpJsl9If4H^9bdIU{GDaY;5=j1_ri`IdXGzZ_IZ{FX<2EO1sq>Lf3;C zj{#)qAlL#X5Vp#q#!f7xncOu=fqxpf({-%;>GJ7jgmUqVlb!#B;@*YH9F?fzLcubH zr{U8!%ac|Pi@Bl#=g`on4i=Xedi;$+Lxu zgs|`zULIgltgMj~H^VTdt={ZXQs!lMTTQF_`$6$@0I*4k2|OU`RNWZip;d24w4nMr zI5+?_Vw`WBw)j5;##`65v}DZE&&64758k4@G05Qb4W^>PMGxOSTgDu}Kb&)H0MY!c zqfRu%?z42Az0O~af3VsB*1uCY{KH#(!}k!xD}ZRdOzOvY^=}BAuFq|O2ABoXG$@|k zYYW#BmuChSRP{67LthK@*}U)WE*tv^{a_$7LI+IjaFOWrK9WQ)FkGsF`Tp%2GYgBb zs3A0PZRbwumqZOUAD^?M%_3m62%_cOllUz%GMdp`(9K}^w{=^CkqX1H zU|iV{Y;RZB_J~hhKY6De8>);Oo;;I>?nWapA!Gk`5U+-YG0Kq8%md6cgX^ZkP5ipBaM<2kbGmU$52YP?ZNZ(!xm)%bXUk%hjcwa!_ zV|9SU25Z3Zp!?LhZHGuX<**lu8vfv>ky3HsH6uR=7=8*+Ui=(_C&{wev#mA-1< zd)n=$^SZoL6m^0M9p{@Bb2T>$xqBEzjNNK1&oyp;>E}AISl**w?}+{)H_vWb;-V8x zwKoUpbh2KAoJTAX%b|f7uIP`J@o}sru^R1c;DvWu_D#AGffF9Xct6IQSVp?HF-ZSz zs|Z}owe3$u(#nK@vU{E@fIwJBDru!(s(_RH^+puio2bz}YibW0_c*oJo6i62}v zlFm=|*3~ae3>8a=8FHgicoEFL6TD$-QMINt&avtHO5l>mZd<60 zC5%#)-WT Date: Mon, 26 Oct 2015 18:07:16 +0100 Subject: [PATCH 372/487] Use \section to get nice tree view in the left pane --- Triangulation/doc/Triangulation/Triangulation.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 9fd8faf00b9..eeee2dc049d 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -16,7 +16,7 @@ combinatorial aspect of triangulations while the geometric classes compute and maintain triangulations, Delaunay triangulations and regular triangulations of sets of points. -# Introduction # +\section TriangulationSecIntro Introduction ## Some Definitions ## @@ -106,7 +106,7 @@ If the maximal dimension of a simplex in the triangulation is Two faces \f$ \sigma\f$ and \f$ \sigma'\f$ are incident if and only if \f$ \sigma'\f$ is a proper sub-face of \f$ \sigma\f$ or vice versa. -# %Triangulation Data Structure # +\section TriangulationSecTDS Triangulation Data Structure In this section, we describe the concept `TriangulationDataStructure` for which \cgal provides one model class: @@ -126,7 +126,7 @@ us denote the maximal dimension with \f$ D \f$ and the current dimension with \f The inequalities \f$ -2 \leq d \leq D\f$ and \f$ 0 \le D\f$ always hold. The special meaning of negative values for \f$d\f$ is explained below. -### The Set of Faces ### +## The Set of Faces ## The set of faces of a `TriangulationDataStructure` with current dimension \f$ d \f$ forms a triangulation of the @@ -291,7 +291,7 @@ Barycentric subdivision in dimension \f$ d=2\f$. \cgalExample{barycentric_subdivision.cpp} -# Triangulations # +\section TriangulationSecTriangulations Triangulations The class `CGAL::Triangulation` maintains a triangulation embedded in Euclidean space. The triangulation @@ -388,7 +388,7 @@ One important difference between the two examples above is that the first uses visits only the infinite full cells but stores handles to them into the potentially big array infinite_full_cells. -# Delaunay Triangulations # +\section TriangulationSecDT Delaunay Triangulations The class `CGAL::Delaunay_triangulation` derives from `CGAL::Triangulation` @@ -510,7 +510,7 @@ This simple example shows how to create a regular triangulation. \cgalExample{regular_triangulation.cpp} -# Complexity and Performances # +\section TriangulationSecPerf Complexity and Performances The current implementation locates points by walking in the triangulation, and sorts the points with spatial sort to insert a @@ -565,7 +565,7 @@ Performance of the insertion of 1000 points in a Delaunay triangulation. Running time wrt. number of maximal simplices, for dimensions for 2 to 12. \cgalFigureEnd -# Design and Implementation History # +\section TriangulationSecDesign Design and Implementation History This package is heavily inspired by the works of Monique Teillaud and Sylvain Pion (`Triangulation_3`) From 0013e96a9fdecdb1244c8809732b6974c375d085 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Oct 2015 12:50:52 +0100 Subject: [PATCH 373/487] Oops --- Triangulation/doc/Triangulation/PackageDescription.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 82e743c13d5..312cf68e657 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -73,8 +73,8 @@ is opposite to the vertex with the same index. ## Triangulation Data Structure ## - `TriangulationDataStructure` -- `TriangulationDataStructure_2::FullCell` -- `TriangulationDataStructure_2::Vertex` +- `TriangulationDataStructure::FullCell` +- `TriangulationDataStructure::Vertex` - `TriangulationDSVertex` - `TriangulationDSFullCell` - `TriangulationDSFace` From a186ec9f33716922de32af5b989a78ed258bcc28 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Oct 2015 12:51:28 +0100 Subject: [PATCH 374/487] Fix some "`" --- .../Triangulation/CGAL/Triangulation_data_structure.h | 4 ++-- .../Concepts/DelaunayTriangulationTraits.h | 2 +- .../Concepts/RegularTriangulationTraits.h | 2 +- .../doc/Triangulation/Concepts/TriangulationTraits.h | 10 +++++----- Triangulation/doc/Triangulation/Triangulation.txt | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation_data_structure.h b/Triangulation/doc/Triangulation/CGAL/Triangulation_data_structure.h index 7c9eb2de21d..9d374c693f8 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation_data_structure.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation_data_structure.h @@ -12,12 +12,12 @@ Parameters `Dimensionality` can be either

      -
    • CGAL::`Dimension_tag` for some integer `D`. This +
    • `CGAL::Dimension_tag` for some integer `D`. This indicates that the triangulation data structure can store simplices (full cells) of dimension at most `D`. The maximal dimension `D` is known by the compiler, which triggers some optimizations. Or -
    • CGAL::`Dynamic_dimension_tag`. In this case, the maximum +
    • `CGAL::Dynamic_dimension_tag`. In this case, the maximum dimension of the simplices (full cells) is passed as an integer argument to an instance constructor (see `TriangulationDataStructure`).
    diff --git a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h index ff0e09edfb5..f575caea9ee 100644 --- a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h @@ -32,7 +32,7 @@ defined by the points in range `[start,end)`. If the simplex is positively oriented, then the positive side of sphere corresponds geometrically to its bounded side. -\pre If `Dimension`=`CGAL::``Dimension_tag`, +\pre If `Dimension`=`CGAL::Dimension_tag`, then `std::distance(start,end)=D+1`. The points in range `[start,end)` must be affinely independent, i.e., the simplex must diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index b349115197d..4be5635e789 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -61,7 +61,7 @@ The operator returns: - `ON_POSITIVE_SIDE` if `p` lies inside this oriented sphere. -\pre If `Dimension`=`CGAL::``Dimension_tag`, +\pre If `Dimension`=`CGAL::Dimension_tag`, then `std::distance(start,end)=D+1`. The points in range `[start,end)` must be affinely independent, i.e., the simplex must diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h index 36e2b8a5d33..70dfd38cebd 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h @@ -30,8 +30,8 @@ A type representing the dimension of the predicates (but not necessarily the one of `Point_d`). If \f$ n \f$ is the number of points required by the `Orientation_d` predicate, then `Dimension` \f$ = n - 1\f$. -It can be static (`Dimension`=`CGAL::``Dimension_tag`) or -dynamic (`Dimension`=`CGAL::``Dynamic_dimension_tag`). +It can be static (`Dimension`=`CGAL::Dimension_tag`) or +dynamic (`Dimension`=`CGAL::Dynamic_dimension_tag`). */ typedef unspecified_type Dimension; @@ -48,7 +48,7 @@ templated operator The operator returns the orientation of the simplex defined by the points in the range `[start, end)`; the value can be `CGAL::POSITIVE`, `CGAL::NEGATIVE` or `CGAL::COPLANAR`. -\pre If `Dimension`=`CGAL::``Dimension_tag`, then `std::distance(start,end)=D+1`. +\pre If `Dimension`=`CGAL::Dimension_tag`, then `std::distance(start,end)=D+1`. */ typedef unspecified_type Orientation_d; @@ -59,7 +59,7 @@ the templated operator The operator returns `true` if and only if point `p` is contained in the affine space spanned by the points in the range `[start, end)`. That affine space is also called the affine hull of the points in the range. -\pre If `Dimension`=`CGAL::``Dimension_tag`, +\pre If `Dimension`=`CGAL::Dimension_tag`, then `std::distance(start,end)=D+1`. The points in the range must be affinely independent. Note that in the CGAL kernels, this predicate @@ -97,7 +97,7 @@ the range `R=[start, end)` can be oriented in two different ways, the operator returns an object that allow to orient that flat so that `R=[start, end)` defines a positive simplex. -\pre If `Dimension`=`CGAL::``Dimension_tag`, +\pre If `Dimension`=`CGAL::Dimension_tag`, then `std::distance(start,end)=D+1`. The points in range `[start,end)` must be affinely independent. diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index eeee2dc049d..4003d86e210 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -222,11 +222,11 @@ the user needs custom types (see the reference manual page for this class template). The first template parameter, `Dimensionality`, must be one of the following:
      -
    • CGAL::`Dimension_tag` for some integer \f$ D \f$. This +
    • `CGAL::Dimension_tag` for some integer \f$ D \f$. This indicates that the triangulation can store full cells of dimension at most \f$ D \f$. The maximum dimension \f$ D \f$ is known by the compiler, which triggers some optimizations. -
    • CGAL::`Dynamic_dimension_tag`. In this case, the maximum +
    • `CGAL::Dynamic_dimension_tag`. In this case, the maximum dimension of the full cells must be passed as an integer argument to an instance constructor (see `TriangulationDataStructure`).
    From c7e1c825cd7420ef142be66153f68ff594998561 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Oct 2015 15:19:37 +0100 Subject: [PATCH 375/487] Document Regular_triangulation_euclidean_traits --- .../CGAL/Regular_triangulation.h | 3 ++- .../Regular_triangulation_euclidean_traits.h | 25 +++++++++++++++++++ .../doc/Triangulation/PackageDescription.txt | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 8e530137e38..115d03cef74 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -45,7 +45,8 @@ Parameters \tparam RegularTriangulationTraits is the geometric traits class that provides the geometric types and predicates needed by regular triangulations. `RegularTriangulationTraits` must be a model of the concept -`RegularTriangulationTraits`. +`RegularTriangulationTraits`. CGAL provides the class +`Regular_triangulation_euclidean_traits` for this purpose. \tparam TriangulationDataStructure must be a model of the concept `TriangulationDataStructure`. This model is used to store diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h new file mode 100644 index 00000000000..b4d716132fe --- /dev/null +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h @@ -0,0 +1,25 @@ + +namespace CGAL { + + /*! + \ingroup PkgTriangulationsTriangulationClasses + + The class `Regular_triangulation_euclidean_traits` is designed as a traits + class for the class + `Regular_triangulation`. + + \tparam K must be a model of the `Kernel_d` concept. We recommend to use + `Epick_d`. + + \tparam Weight is optional. If is it not provided, `K::RT` will be used. + + \cgalModels `RegularTriangulationTraits` + */ +template < class K, class Weight = typename K::RT > +class Regular_triangulation_euclidean_traits + : public K +{ +}; + +} //namespace CGAL + diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 312cf68e657..11a2c0d2cb8 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -106,6 +106,7 @@ The latter two concepts are also abbreviated respectively as `TrVertex` and `TrF - `CGAL::Regular_triangulation` - `CGAL::Triangulation_vertex` - `CGAL::Triangulation_full_cell` +- `CGAL::Regular_triangulation_euclidean_traits` ## Enums ## From b6a6ee20c62461dfa4b100d35ac66eca1352d181 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Oct 2015 15:23:59 +0100 Subject: [PATCH 376/487] Put the traits in a separate group --- .../CGAL/Regular_triangulation_euclidean_traits.h | 2 +- Triangulation/doc/Triangulation/PackageDescription.txt | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h index b4d716132fe..5aeadf5b9c6 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h @@ -2,7 +2,7 @@ namespace CGAL { /*! - \ingroup PkgTriangulationsTriangulationClasses + \ingroup PkgTriangulationsTraitsClasses The class `Regular_triangulation_euclidean_traits` is designed as a traits class for the class diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 11a2c0d2cb8..e307e02dfa2 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -8,6 +8,9 @@ /// \defgroup PkgTriangulationsVertexCellClasses Vertex, Face and Cell Classes /// \ingroup PkgTriangulations +/// \defgroup PkgTriangulationsTraitsClasses Traits Classes +/// \ingroup PkgTriangulations + /*! \addtogroup PkgTriangulations \cgalPkgDescriptionBegin{dD Triangulations,PkgTriangulationsSummary} @@ -106,6 +109,9 @@ The latter two concepts are also abbreviated respectively as `TrVertex` and `TrF - `CGAL::Regular_triangulation` - `CGAL::Triangulation_vertex` - `CGAL::Triangulation_full_cell` + +## Traits ## + - `CGAL::Regular_triangulation_euclidean_traits` ## Enums ## From 2b689787fedb14fad691095380ade0e02f5ed956 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Oct 2015 16:36:30 +0100 Subject: [PATCH 377/487] Regular_triangulation_euclidean_traits now satisfies SpatialSortingTraits_d --- .../include/CGAL/Regular_triangulation.h | 12 ++------ .../Regular_triangulation_euclidean_traits.h | 30 +++++++++++++++++-- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 7eb73c545e6..a3b642a570f 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -223,16 +223,8 @@ public: size_type n = number_of_vertices(); typedef std::vector WP_vec; WP_vec points(start, end); - - typedef boost::function_property_map< - typename Geom_traits::Point_drop_weight_d, - Weighted_point, - Bare_point> Drop_weight_pmap; - typedef CGAL::Spatial_sort_traits_adapter_d< - typename Geom_traits::Base, Drop_weight_pmap> Search_traits_d; - Search_traits_d st_d(boost::make_function_property_map( - geom_traits().point_drop_weight_d_object())); - spatial_sort(points.begin(), points.end(), st_d); + + spatial_sort(points.begin(), points.end(), geom_traits()); Full_cell_handle hint; for(typename WP_vec::const_iterator p = points.begin(); p != points.end(); ++p ) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index c5643ae2d06..e8b6b7796e0 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -50,7 +50,28 @@ public: //=========================================================================== // Custom types //=========================================================================== - + + // Required by SpatialSortingTraits_d + class Less_coordinate_d + { + const K &m_kernel; + + public: + typedef bool result_type; + + Less_coordinate_d(const K &kernel) + : m_kernel(kernel) {} + + result_type operator()( + Weighted_point const& p, Weighted_point const& q, int i) const + { + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + return m_kernel.less_coordinate_d_object() (pdw(p), pdw(q), i); + } + }; + + //=========================================================================== + // Required by TriangulationTraits class Orientation_d { @@ -195,7 +216,8 @@ public: //=========================================================================== - // Only for Triangulation_off_ostream.h (undocumented) + // To satisfy SpatialSortingTraits_d + // and also for Triangulation_off_ostream.h (undocumented) class Point_dimension_d { const K &m_kernel; @@ -218,6 +240,10 @@ public: // Object creation //=========================================================================== + Less_coordinate_d less_coordinate_d_object() const + { + return Less_coordinate_d(*this); + } Contained_in_affine_hull_d contained_in_affine_hull_d_object() const { return Contained_in_affine_hull_d(*this); From 232efb98238c1501d62c65e1732b5eaa10454b84 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Oct 2015 17:27:46 +0100 Subject: [PATCH 378/487] Hide Regular_triangulation_euclidean_traits from the doc and use it internally The user can now pass Epick_d directly to Regular_triangulation. Regular_triangulation_euclidean_traits is used internally to adapt the functors. --- .../Triangulation/points_to_RT_to_off.cpp | 4 +- .../Triangulation/Td_vs_T2_and_T3.cpp | 4 +- .../CGAL/Regular_triangulation.h | 3 +- .../Regular_triangulation_euclidean_traits.h | 25 ----- .../Concepts/RegularTriangulationTraits.h | 9 +- .../doc/Triangulation/PackageDescription.txt | 7 -- .../Triangulation/regular_triangulation.cpp | 8 +- .../include/CGAL/Regular_triangulation.h | 92 ++++++++++--------- .../Triangulation/test_insert_if_in_star.cpp | 4 +- .../test/Triangulation/test_regular.cpp | 4 +- 10 files changed, 58 insertions(+), 102 deletions(-) delete mode 100644 Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h diff --git a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp index 94a633a505d..c882330d392 100644 --- a/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp +++ b/Triangulation/applications/Triangulation/points_to_RT_to_off.cpp @@ -1,13 +1,11 @@ #include -#include #include #include #include typedef CGAL::Epick_d K; -typedef CGAL::Regular_triangulation_euclidean_traits Traits; -typedef CGAL::Regular_triangulation RT; +typedef CGAL::Regular_triangulation RT; void test(int dim) { diff --git a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp index 3c9bacc51cd..2c4ac1c98a9 100644 --- a/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp +++ b/Triangulation/benchmark/Triangulation/Td_vs_T2_and_T3.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -156,8 +155,7 @@ void go(const int N) points_d.push_back(Point_d(D, coords[i].begin(), coords[i].end())); // RTd - typedef CGAL::Regular_triangulation_euclidean_traits Traits_d; - typedef CGAL::Regular_triangulation RT_d; + typedef CGAL::Regular_triangulation RT_d; typedef typename RT_d::Bare_point Bare_point_d; typedef typename RT_d::Point WPoint_d; diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 115d03cef74..8e530137e38 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -45,8 +45,7 @@ Parameters \tparam RegularTriangulationTraits is the geometric traits class that provides the geometric types and predicates needed by regular triangulations. `RegularTriangulationTraits` must be a model of the concept -`RegularTriangulationTraits`. CGAL provides the class -`Regular_triangulation_euclidean_traits` for this purpose. +`RegularTriangulationTraits`. \tparam TriangulationDataStructure must be a model of the concept `TriangulationDataStructure`. This model is used to store diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h deleted file mode 100644 index 5aeadf5b9c6..00000000000 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h +++ /dev/null @@ -1,25 +0,0 @@ - -namespace CGAL { - - /*! - \ingroup PkgTriangulationsTraitsClasses - - The class `Regular_triangulation_euclidean_traits` is designed as a traits - class for the class - `Regular_triangulation`. - - \tparam K must be a model of the `Kernel_d` concept. We recommend to use - `Epick_d`. - - \tparam Weight is optional. If is it not provided, `K::RT` will be used. - - \cgalModels `RegularTriangulationTraits` - */ -template < class K, class Weight = typename K::RT > -class Regular_triangulation_euclidean_traits - : public K -{ -}; - -} //namespace CGAL - diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 4be5635e789..6690823286b 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -25,18 +25,13 @@ An arithmetic field type. typedef unspecified_type FT; /*! -The weighted point type. Must be the same type as `TriangulationTraits::Point_d`. +The weighted point type. */ typedef unspecified_type Weighted_point; -/*! -The un-weighted point type. -*/ -typedef unspecified_type Bare_point; - /*! A predicate object that must provide the operator -`Bare_point operator()(const Weighted_point & wp)`, returning +`Point_d operator()(const Weighted_point & wp)`, returning `wp` without its weight. */ typedef unspecified_type Point_drop_weight_d; diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index e307e02dfa2..312cf68e657 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -8,9 +8,6 @@ /// \defgroup PkgTriangulationsVertexCellClasses Vertex, Face and Cell Classes /// \ingroup PkgTriangulations -/// \defgroup PkgTriangulationsTraitsClasses Traits Classes -/// \ingroup PkgTriangulations - /*! \addtogroup PkgTriangulations \cgalPkgDescriptionBegin{dD Triangulations,PkgTriangulationsSummary} @@ -110,10 +107,6 @@ The latter two concepts are also abbreviated respectively as `TrVertex` and `TrF - `CGAL::Triangulation_vertex` - `CGAL::Triangulation_full_cell` -## Traits ## - -- `CGAL::Regular_triangulation_euclidean_traits` - ## Enums ## - `CGAL::Triangulation::Locate_type` diff --git a/Triangulation/examples/Triangulation/regular_triangulation.cpp b/Triangulation/examples/Triangulation/regular_triangulation.cpp index 941a5e5ba19..a8a917db17e 100644 --- a/Triangulation/examples/Triangulation/regular_triangulation.cpp +++ b/Triangulation/examples/Triangulation/regular_triangulation.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -11,10 +10,9 @@ const int D = 5; // Dimension const int N = 100; // Number of points typedef CGAL::Epick_d< CGAL::Dimension_tag > K; -typedef CGAL::Regular_triangulation_euclidean_traits Traits; -typedef Traits::Bare_point Bare_point; -typedef Traits::Weighted_point Weighted_point; -typedef CGAL::Regular_triangulation T; +typedef CGAL::Regular_triangulation T; +typedef T::Bare_point Bare_point; +typedef T::Weighted_point Weighted_point; int main() { diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index a3b642a570f..a1f71d31c01 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -24,33 +24,37 @@ #include #include #include -#include +#include #include namespace CGAL { -template< typename RTTraits, typename TDS_ = Default > +template< typename Traits_, typename TDS_ = Default > class Regular_triangulation : public Triangulation< - RTTraits, - typename Default::Get, - Triangulation_full_cell > - >::type > + CGAL::Regular_triangulation_euclidean_traits, + typename Default::Get< + TDS_, + Triangulation_data_structure< + typename CGAL::Regular_triangulation_euclidean_traits::Dimension, + Triangulation_vertex >, + Triangulation_full_cell > + > + >::type> { - typedef typename RTTraits::Dimension Maximal_dimension_; + typedef CGAL::Regular_triangulation_euclidean_traits RTTraits; + typedef typename RTTraits::Dimension Maximal_dimension_; typedef typename Default::Get< TDS_, Triangulation_data_structure< - Maximal_dimension_, - Triangulation_vertex, - Triangulation_full_cell - > >::type TDS; - typedef Triangulation Base; - typedef Regular_triangulation Self; - + Maximal_dimension_, + Triangulation_vertex, + Triangulation_full_cell + > >::type TDS; + typedef Triangulation Base; + typedef Regular_triangulation Self; + typedef typename RTTraits::Orientation_d Orientation_d; typedef typename RTTraits::Power_test_d Power_test_d; typedef typename RTTraits::In_flat_power_test_d In_flat_power_test_d; @@ -465,9 +469,9 @@ private: // Warning: this function is not correct since it does not restore hidden // vertices -template< typename RTTraits, typename TDS > -typename Regular_triangulation::Full_cell_handle -Regular_triangulation +template< typename Traits, typename TDS > +typename Regular_triangulation::Full_cell_handle +Regular_triangulation ::remove( Vertex_handle v ) { CGAL_precondition( ! is_infinite(v) ); @@ -522,12 +526,12 @@ Regular_triangulation typedef Triangulation_vertex Dark_vertex_base; typedef Triangulation_full_cell< Geom_traits, - internal::Triangulation::Dark_full_cell_data > Dark_full_cell_base; + internal::Triangulation::Dark_full_cell_data > Dark_full_cell_base; typedef Triangulation_data_structure Dark_tds; - typedef Regular_triangulation Dark_triangulation; + typedef Regular_triangulation Dark_triangulation; typedef typename Dark_triangulation::Face Dark_face; typedef typename Dark_triangulation::Facet Dark_facet; typedef typename Dark_triangulation::Vertex_handle Dark_v_handle; @@ -762,9 +766,9 @@ Regular_triangulation return ret_s; } -template< typename RTTraits, typename TDS > +template< typename Traits, typename TDS > void -Regular_triangulation +Regular_triangulation ::remove_decrease_dimension(Vertex_handle v) { CGAL_precondition( current_dimension() >= 0 ); @@ -785,9 +789,9 @@ Regular_triangulation // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS -template< typename RTTraits, typename TDS > -typename Regular_triangulation::Vertex_handle -Regular_triangulation +template< typename Traits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation ::insert(const Weighted_point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) { switch( lt ) @@ -821,9 +825,9 @@ Regular_triangulation } } -template< typename RTTraits, typename TDS > -typename Regular_triangulation::Vertex_handle -Regular_triangulation +template< typename Traits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation ::insert_outside_affine_hull(const Weighted_point & p) { // we don't use Base::insert_outside_affine_hull(...) because here, we @@ -870,9 +874,9 @@ Regular_triangulation return v; } -template< typename RTTraits, typename TDS > -typename Regular_triangulation::Vertex_handle -Regular_triangulation +template< typename Traits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation ::insert_if_in_star(const Weighted_point & p, const Vertex_handle star_center, const Locate_type lt, const Face & f, const Facet & ft, @@ -910,9 +914,9 @@ Regular_triangulation return Vertex_handle(); } -template< typename RTTraits, typename TDS > -typename Regular_triangulation::Vertex_handle -Regular_triangulation +template< typename Traits, typename TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation ::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s, const Vertex_handle only_if_this_vertex_is_in_the_cz) @@ -960,10 +964,10 @@ Regular_triangulation // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES // NOT DOCUMENTED -template< typename RTTraits, typename TDS > +template< typename Traits, typename TDS > template< typename OrientationPred > Oriented_side -Regular_triangulation +Regular_triangulation ::perturbed_power_test(const Weighted_point & p, Full_cell_const_handle s, const OrientationPred & ori) const { @@ -1018,9 +1022,9 @@ Regular_triangulation return ON_NEGATIVE_SIDE; } -template< typename RTTraits, typename TDS > +template< typename Traits, typename TDS > bool -Regular_triangulation +Regular_triangulation ::is_in_conflict(const Weighted_point & p, Full_cell_const_handle s) const { CGAL_precondition( 1 <= current_dimension() ); @@ -1041,10 +1045,10 @@ Regular_triangulation } } -template< typename RTTraits, typename TDS > +template< typename Traits, typename TDS > template< typename OutputIterator > -typename Regular_triangulation::Facet -Regular_triangulation +typename Regular_triangulation::Facet +Regular_triangulation ::compute_conflict_zone(const Weighted_point & p, const Full_cell_handle s, OutputIterator out) const { CGAL_precondition( 1 <= current_dimension() ); @@ -1069,9 +1073,9 @@ Regular_triangulation // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY -template< typename RTTraits, typename TDS > +template< typename Traits, typename TDS > bool -Regular_triangulation +Regular_triangulation ::is_valid(bool verbose, int level) const { if (!Base::is_valid(verbose, level)) diff --git a/Triangulation/test/Triangulation/test_insert_if_in_star.cpp b/Triangulation/test/Triangulation/test_insert_if_in_star.cpp index 3621c034fbc..4aeb5204566 100644 --- a/Triangulation/test/Triangulation/test_insert_if_in_star.cpp +++ b/Triangulation/test/Triangulation/test_insert_if_in_star.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -81,8 +80,7 @@ void go(const int N) { //typedef CGAL::Epick_d FK; typedef CGAL::Epick_d > FK; - typedef CGAL::Regular_triangulation_euclidean_traits Traits; - typedef CGAL::Regular_triangulation Triangulation; + typedef CGAL::Regular_triangulation Triangulation; //test(D, "dynamic", N); test(D, "static", N); } diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index 01aa6d957c5..fc319e39ff0 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -110,8 +109,7 @@ void go(const int N) { //typedef CGAL::Epick_d FK; typedef CGAL::Epick_d > FK; - typedef CGAL::Regular_triangulation_euclidean_traits Traits; - typedef CGAL::Regular_triangulation Triangulation; + typedef CGAL::Regular_triangulation Triangulation; //test(D, "dynamic", N); test(D, "static", N); } From 13084b083597ace53d5f5aba58dc36bb01adfb83 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Oct 2015 18:08:51 +0100 Subject: [PATCH 379/487] Bare_point is not in RegularTriangulationTraits any more. --- Triangulation/doc/Triangulation/Triangulation.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 4003d86e210..f5a5fbfb4d3 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -498,8 +498,8 @@ the concept `TriangulationDataStructure` which is instantiated with a vertex type that stores a weighted point and allows its retrieval. The template parameter `RegularTriangulationTraits` must be a model of the concept -`RegularTriangulationTraits` which provides the `Bare_point`and `%Weighted_point` -types as well as various geometric predicates used by the +`RegularTriangulationTraits` which provides the and `%Weighted_point` +type as well as various geometric predicates used by the `Regular_triangulation` class. The concept `RegularTriangulationTraits` refines the concept `TriangulationTraits`. From f6d74e301561cb7b1aa1e2a8a318402d52fb5f4d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Oct 2015 19:11:25 +0100 Subject: [PATCH 380/487] Missing _d --- .../doc/Triangulation/Concepts/RegularTriangulationTraits.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 6690823286b..c6f5bd091b3 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -27,7 +27,7 @@ typedef unspecified_type FT; /*! The weighted point type. */ -typedef unspecified_type Weighted_point; +typedef unspecified_type Weighted_point_d; /*! A predicate object that must provide the operator From baed1ab6afcd1fbcd0410cf12995e513cd4820f7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Oct 2015 14:37:38 +0100 Subject: [PATCH 381/487] Add RegularTriangulationTraits here --- Kernel_d/doc/Kernel_d/CGAL/Epick_d.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h index 04b748c8bc4..7ef31d04699 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h @@ -37,6 +37,7 @@ icc 15 work. \cgalModels `Kernel_d` \cgalModels `DelaunayTriangulationTraits` +\cgalModels `RegularTriangulationTraits` \sa `CGAL::Cartesian_d` \sa `CGAL::Homogeneous_d` From 49d1292a7dc0579c37aa44b4b12a36340aa74aed Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 28 Oct 2015 15:40:45 +0100 Subject: [PATCH 382/487] Document the constructor of Epick_d::Weighted_point_d. --- Kernel_d/doc/Kernel_d/CGAL/Epick_d.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h index 7ef31d04699..e2ecc927472 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h @@ -75,6 +75,21 @@ Cartesian_const_iterator_d cartesian_begin()const; Cartesian_const_iterator_d cartesian_end()const; }; +/*! +represents a weighted point in the Euclidean space +\cgalModels `DefaultConstructible` +\cgalModels `Assignable` +*/ +class Weighted_point_d { +public: +/*! introduces a weighted point with point p and weight w. */ +Weighted_point_d(const Point_d& p, const FT& w); +/*! extracts the point of a weighted point. */ +Point_d point()const; +/*! extracts the weight of a weighted point. */ +FT weight()const; +}; + /*! \cgalModels `Kernel_d::Center_of_sphere_d` */ struct Construct_circumcenter_d { From 093295a55314beb34ed79a07860342607816ec16 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Oct 2015 17:18:01 +0100 Subject: [PATCH 383/487] Use "double" for consistency --- Kernel_d/doc/Kernel_d/CGAL/Epick_d.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h index e2ecc927472..a48fedce5e0 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h @@ -83,11 +83,11 @@ represents a weighted point in the Euclidean space class Weighted_point_d { public: /*! introduces a weighted point with point p and weight w. */ -Weighted_point_d(const Point_d& p, const FT& w); +Weighted_point_d(const Point_d& p, const double& w); /*! extracts the point of a weighted point. */ -Point_d point()const; +Point_d point() const; /*! extracts the weight of a weighted point. */ -FT weight()const; +double weight() const; }; /*! \cgalModels `Kernel_d::Center_of_sphere_d` From bb34ded1eaf33ce75aeb589b7e019c92cfc037a2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Nov 2015 11:52:06 +0100 Subject: [PATCH 384/487] Option EXPORT_POINTS_TO_A_FILE --- .../benchmark/Triangulation/delaunay.cpp | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/Triangulation/benchmark/Triangulation/delaunay.cpp b/Triangulation/benchmark/Triangulation/delaunay.cpp index a1e54c12379..acf913d56f8 100644 --- a/Triangulation/benchmark/Triangulation/delaunay.cpp +++ b/Triangulation/benchmark/Triangulation/delaunay.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -13,6 +14,7 @@ //#define USE_DYNAMIC_KERNEL #define OUTPUT_STATS_IN_CSV +//#define EXPORT_POINTS_TO_A_FILE #ifdef OUTPUT_STATS_IN_CSV static std::ofstream csv_file("stats.csv"); @@ -47,6 +49,15 @@ std::size_t compute_triangulation(std::size_t N) Random_points_iterator rand_it(D, 2.0, rng); CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); +#ifdef EXPORT_POINTS_TO_A_FILE + std::ofstream os("points.txt"); + for (auto const& p : points) + { + CGAL::Triangulation_IO::output_point(os, K(), p); + os << std::endl; + } +#endif + std::size_t mem_before = CGAL::Memory_sizer().virtual_size(); cost.reset(); cost.start(); @@ -101,17 +112,17 @@ int main(int argc, char **argv) { srand(static_cast(time(NULL))); //int N = 100; if( argc > 1 ) N = atoi(argv[1]); - go<2>(5000000); // 1e7 - go<3>(1000000); // 1e6 - go<4>(300000); // 1e5 - go<5>(50000); // 1e4 - go<6>(5000); - go<7>(1000); - go<8>(300); - go<9>(100); - go<10>(30); - go<11>(20); - go<12>(15); + go<2>(5000000); + //go<3>(1000000); + //go<4>(300000); + //go<5>(50000); + //go<6>(5000); + //go<7>(1000); + //go<8>(300); + //go<9>(100); + //go<10>(30); + //go<11>(20); + //go<12>(15); return 0; } From edacc0f8c5372bb427fd3c84202ed085a897ba61 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 24 Nov 2015 16:01:20 +0100 Subject: [PATCH 385/487] Prettify the code --- .../Triangulation/delaunay_triangulation.cpp | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp index 6f500ab9932..0d186f452bf 100644 --- a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp +++ b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp @@ -17,13 +17,14 @@ typedef CGAL::Delaunay_triangulation T; int main(int argc, char **argv) { - int N = 100; if( argc > 2 )N = atoi(argv[1]); // number of points + int N = 100; // number of points + if( argc > 1 ) + N = atoi(argv[1]); CGAL::Timer cost; // timer - // Instanciate a random point generator + // Generate N random points typedef CGAL::Random_points_in_cube_d Random_points_iterator; Random_points_iterator rand_it(D, 1.0, CGAL::get_default_random()); - // Generate N random points std::vector points; CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); @@ -31,16 +32,18 @@ int main(int argc, char **argv) CGAL_assertion(t.empty()); // insert the points in the triangulation - cost.reset();cost.start(); - std::cout << " Delaunay triangulation of "< out(zone); c = t.locate(*++rand_it, lt, f, ft, v); - // previously inserted vertex v is used as hint for point location (if defined) + + // Previously inserted vertex v is used as hint for point location (if defined) T::Facet ftc = t.compute_conflict_zone(*rand_it, c, out); - std::cout< "< " + << std::flush; out = std::back_inserter(new_full_cells); - CGAL_assertion( t.is_valid() ); + CGAL_assertion(t.is_valid()); v = t.insert_in_hole(*rand_it, zone.begin(), zone.end(), ftc, out); - std::cout< Date: Thu, 3 Dec 2015 14:47:49 +0100 Subject: [PATCH 386/487] Warning if sparsity = 0 + bugfixes --- Tangential_complex/include/CGAL/Tangential_complex.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index eba7bce121a..d430d3d1c3a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -302,7 +302,10 @@ public: , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) #endif - { } + { + if (sparsity <= 0.) + std::cerr << "!Warning! Sparsity should be > 0\n"; + } /// Destructor ~Tangential_complex() @@ -517,7 +520,7 @@ public: # ifdef CGAL_TC_VERBOSE std::cerr << "Nothing to fix." << std::endl; # endif - return 0; + return TC_FIXED; } #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES @@ -682,7 +685,7 @@ public: << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl << " * Percentage of inconsistencies: " - << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl + << 100. * num_inconsistent_simplices / num_simplices << "%" << std::endl << "==========================================================" << std::endl; } From e62b5513e1081a0428c5e838a3f8ec7e8dfcc7ea Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 3 Dec 2015 15:40:52 +0100 Subject: [PATCH 387/487] Macros: TC_INPUT_STRIDES + CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY --- .../Tangential_complex/benchmark_tc.cpp | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index b90dce674e4..72e599a42ff 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -40,6 +41,8 @@ typedef CGAL::Tangential_complex< CGAL::Parallel_tag> TC; //#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test +//#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY +#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points #ifdef JUST_BENCHMARK_SPATIAL_SEARCH std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); @@ -186,7 +189,7 @@ bool export_to_off( } else { -#ifdef CGAL_ALPHA_TC +/*#ifdef CGAL_ALPHA_TC TC::Simplicial_complex complex; tc.export_TC(complex, false); tc.export_to_off( @@ -194,13 +197,13 @@ bool export_to_off( p_simpl_to_color_in_red, p_simpl_to_color_in_green, p_simpl_to_color_in_blue); -#else +#else*/ tc.export_to_off( off_stream, color_inconsistencies, p_simpl_to_color_in_red, p_simpl_to_color_in_green, p_simpl_to_color_in_blue); -#endif +//#endif } return true; } @@ -335,8 +338,10 @@ void make_tc(std::vector &points, return;*/ // CJTODO TEMP =========================== +#ifdef CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY if (ambient_dim <= 4) tc.check_if_all_simplices_are_in_the_ambient_delaunay(); +#endif //tc.check_correlation_between_inconsistencies_and_fatness(); @@ -728,7 +733,15 @@ int main() if (!points.empty()) { - make_tc(points, intrinsic_dim, sparsity, +#if defined(TC_INPUT_STRIDES) && TC_INPUT_STRIDES > 1 + auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES); + std::vector points(p.begin(), p.end()); + std::cerr << "****************************************\n" + << "WARNING: taking 1 point every " << TC_INPUT_STRIDES + << " points.\n" + << "****************************************\n"; +#endif + make_tc(points, intrinsic_dim, sparsity, // strided: CJTODO TEMP perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', time_limit_for_perturb, input.c_str()); @@ -757,5 +770,6 @@ int main() std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found." << std::endl; } + system("pause"); return 0; } From 7ea9538a4e1df9844aaed4d59998b04e7ca8429c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 3 Dec 2015 15:44:50 +0100 Subject: [PATCH 388/487] Macro: TC_NO_EXPORT, to disable export into files --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 72e599a42ff..299d1a0458a 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -43,6 +43,7 @@ typedef CGAL::Tangential_complex< //#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test //#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY #define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points +#define TC_NO_EXPORT #ifdef JUST_BENCHMARK_SPATIAL_SEARCH std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); @@ -169,6 +170,9 @@ bool export_to_off( std::set > const *p_simpl_to_color_in_green = NULL, std::set > const *p_simpl_to_color_in_blue = NULL) { +#ifdef TC_NO_EXPORT + return true; +#endif if (tc.intrinsic_dimension() <= 3) { std::stringstream output_filename; @@ -181,11 +185,13 @@ bool export_to_off( if (p_complex) { +#ifndef TC_NO_EXPORT tc.export_to_off( *p_complex, off_stream, p_simpl_to_color_in_red, p_simpl_to_color_in_green, p_simpl_to_color_in_blue); +#endif } else { @@ -734,7 +740,7 @@ int main() if (!points.empty()) { #if defined(TC_INPUT_STRIDES) && TC_INPUT_STRIDES > 1 - auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES); + auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES); // CJTODO C++11 (auto) std::vector points(p.begin(), p.end()); std::cerr << "****************************************\n" << "WARNING: taking 1 point every " << TC_INPUT_STRIDES From 5eb850500a06c618e15fab05e25e7d6180ec0af8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 8 Dec 2015 17:13:04 +0100 Subject: [PATCH 389/487] Add an example for computing convex hull --- .../examples/Triangulation/CMakeLists.txt | 1 + .../examples/Triangulation/convex_hull.cpp | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 Triangulation/examples/Triangulation/convex_hull.cpp diff --git a/Triangulation/examples/Triangulation/CMakeLists.txt b/Triangulation/examples/Triangulation/CMakeLists.txt index f370b6c863c..ea5866bf9fc 100644 --- a/Triangulation/examples/Triangulation/CMakeLists.txt +++ b/Triangulation/examples/Triangulation/CMakeLists.txt @@ -22,6 +22,7 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "barycentric_subdivision.cpp" ) create_single_source_cgal_program( "delaunay_triangulation.cpp" ) + create_single_source_cgal_program( "convex_hull.cpp" ) create_single_source_cgal_program( "regular_triangulation.cpp" ) create_single_source_cgal_program( "triangulation.cpp" ) create_single_source_cgal_program( "triangulation_data_structure_dynamic.cpp" ) diff --git a/Triangulation/examples/Triangulation/convex_hull.cpp b/Triangulation/examples/Triangulation/convex_hull.cpp new file mode 100644 index 00000000000..ba7a85a59d9 --- /dev/null +++ b/Triangulation/examples/Triangulation/convex_hull.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +const int D = 10; +typedef CGAL::Epick_d< CGAL::Dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; +// The triangulation uses the default instanciation of the +// TriangulationDataStructure template parameter + +int main(int argc, char **argv) +{ + int N = 100; // number of points + if (argc > 1) + N = atoi(argv[1]); + + CGAL::Timer cost; // timer + + // Generate N random points + typedef CGAL::Random_points_in_cube_d Random_points_iterator; + Random_points_iterator rand_it(D, 1.0, CGAL::get_default_random()); + std::vector points; + CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); + + T t(D); + CGAL_assertion(t.empty()); + + // insert the points in the triangulation, only if they are outside the + // convex hull + std::cout << " Convex hull of "<::iterator it_p = points.begin() ; + it_p != points.end() ; ++it_p) + { + T::Locate_type lt; + T::Face f(t.maximal_dimension()); + T::Facet ft; + T::Full_cell_handle fch = t.locate(*it_p, lt, f, ft, hint); + if (lt == T::OUTSIDE_CONVEX_HULL || lt == T::OUTSIDE_AFFINE_HULL) + { + hint = t.insert(*it_p, lt, f, ft, fch)->full_cell(); + ++c; + } + else + { + hint = fch; + } + } + + std::cout << " done in " << cost.time() << " seconds.\n"; + std::cout << c << " points where actually inserted.\n"; + CGAL_assertion( t.is_valid() ); + + return 0; +} From a884ff3a1d58a358f90442b8b5500ef5181622f2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 8 Dec 2015 17:34:44 +0100 Subject: [PATCH 390/487] Optimization --- Triangulation/include/CGAL/Triangulation_data_structure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 6cdc3f4d48e..915f93b9775 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -998,7 +998,7 @@ Triangulation_data_structure associate_vertex_with_full_cell(new_s, facet_index, v); set_neighbors(new_s, facet_index, - neighbor(old_s, facet_index), + outside_neighbor, mirror_index(old_s, facet_index)); // add the new full_cell to the list of new full_cells From f07e7181b57723cae26ea1447a0de9ffac408e6e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 9 Dec 2015 10:26:33 +0100 Subject: [PATCH 391/487] Useless line --- .../include/CGAL/Regular_triangulation_euclidean_traits.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index e8b6b7796e0..ec701ee2713 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -209,7 +209,6 @@ public: const Weighted_point & p, const int i) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - m_kernel.compute_coordinate_d_object()(pdw(p), i); return m_kernel.compute_coordinate_d_object()(pdw(p), i); } }; From 307e195d3c5832a3d4bdabd2d29370b54db82b21 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 9 Dec 2015 10:26:33 +0100 Subject: [PATCH 392/487] Useless line (cherry picked from commit f07e7181b57723cae26ea1447a0de9ffac408e6e) --- .../include/CGAL/Regular_triangulation_euclidean_traits.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index e8b6b7796e0..ec701ee2713 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -209,7 +209,6 @@ public: const Weighted_point & p, const int i) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - m_kernel.compute_coordinate_d_object()(pdw(p), i); return m_kernel.compute_coordinate_d_object()(pdw(p), i); } }; From 1ff70ff716f40bb200c832ba4a81e117b0b75858 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 9 Dec 2015 11:13:50 +0100 Subject: [PATCH 393/487] Fix doc --- Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h | 4 ++-- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 8e530137e38..ca3c6786319 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -54,8 +54,8 @@ defaults to `Triangulation_data_structure` whose template parameters are instantiated as follows:
    • `RegularTriangulationTraits::Dimension`
    • -
    • `Triangulation_vertex`
    • -
    • `Triangulation_full_cell`.
    • +
    • `Triangulation_vertex >`
    • +
    • `Triangulation_full_cell >`.
    \tparam Regular_triangulation can diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index a1f71d31c01..308671521af 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -37,7 +37,7 @@ class Regular_triangulation typename Default::Get< TDS_, Triangulation_data_structure< - typename CGAL::Regular_triangulation_euclidean_traits::Dimension, + typename Traits_::Dimension, Triangulation_vertex >, Triangulation_full_cell > > From 2ea1c1fc5293f86c42a028252b30ee551525676d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 10 Dec 2015 16:44:30 +0100 Subject: [PATCH 394/487] Small bugfixes --- .../include/CGAL/Tangential_complex.h | 198 ++++++++++-------- 1 file changed, 106 insertions(+), 92 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d430d3d1c3a..6e0a9280507 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -98,7 +98,7 @@ private: /// The class Tangential_complex represents a tangential complex template < - typename Kernel, // ambiant dimension + typename Kernel_, // ambiant dimension typename DimensionTag, // intrinsic dimension typename Concurrency_tag = CGAL::Parallel_tag, #ifdef CGAL_ALPHA_TC @@ -106,9 +106,7 @@ template < // => we need to force typename Tr = Regular_triangulation < - Regular_triangulation_euclidean_traits< - Epick_d >, - + Epick_d, Triangulation_data_structure < typename Regular_triangulation_euclidean_traits< @@ -122,9 +120,7 @@ template < #else typename Tr = Regular_triangulation < - Regular_triangulation_euclidean_traits< - Epick_d >, - + Epick_d, Triangulation_data_structure < typename Regular_triangulation_euclidean_traits< @@ -139,10 +135,11 @@ template < > class Tangential_complex { - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Weighted_point_d Weighted_point; - typedef typename Kernel::Vector_d Vector; + typedef Kernel_ K; + typedef typename K::FT FT; + typedef typename K::Point_d Point; + typedef typename K::Weighted_point_d Weighted_point; + typedef typename K::Vector_d Vector; typedef Tr Triangulation; typedef typename Triangulation::Geom_traits Tr_traits; @@ -152,8 +149,8 @@ class Tangential_complex typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename Tr_traits::Vector_d Tr_vector; - typedef Basis Tangent_space_basis; - typedef Basis Orthogonal_space_basis; + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; typedef std::vector Points; #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) @@ -172,7 +169,7 @@ class Tangential_complex #endif typedef std::vector Translations_for_perturb; - typedef Point_cloud_data_structure Points_ds; + typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; typedef typename Points_ds::INS_range INS_range; @@ -276,7 +273,7 @@ public: #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM InputIterator first_for_tse, InputIterator last_for_tse, #endif - const Kernel &k = Kernel() + const K &k = K() ) : m_k(k), m_intrinsic_dim(intrinsic_dimension), @@ -414,8 +411,7 @@ public: void estimate_intrinsic_dimension() const { // Kernel functors - typename Kernel::Compute_coordinate_d coord = - m_k.compute_coordinate_d_object(); + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); std::vector sum_eigen_values(m_ambient_dim, FT(0)); std::size_t num_points_for_pca = static_cast( @@ -589,14 +585,12 @@ public: << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl - << std::endl << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_after.first << std::endl << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%" + << stats_after.second + << " (" << 100. * stats_after.second / stats_after.first << "%)" << std::endl << "==========================================================" << std::endl; @@ -771,9 +765,9 @@ private: std::size_t fill_pqueues_for_alpha_tc(std::size_t i, PQueues &pqueues) { // Kernel/traits functors - typename Kernel::Difference_of_points_d k_diff_points = + typename K::Difference_of_points_d k_diff_points = m_k.difference_of_points_d_object(); - typename Kernel::Squared_length_d k_sqlen = + typename K::Squared_length_d k_sqlen = m_k.squared_length_d_object(); typename Tr_traits::Construct_weighted_point_d constr_wp = m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); @@ -955,9 +949,16 @@ public: // Update the alpha+/- values tangent_basis.update_alpha_values_of_thickening_vectors( saa.m_thickening_vector, m_k); - + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_recomputation; +#endif // Recompute triangulation & star compute_tangent_triangulation(saa.m_center_point_index); +#ifdef CGAL_TC_PROFILING + double recomp_timing = t_recomputation.elapsed(); +#endif + #ifdef CGAL_TC_PERFORM_EXTRA_CHECKS if (!is_simplex_in_star(saa.m_center_point_index, saa.m_simplex)) @@ -967,11 +968,12 @@ public: << "simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << " not added in star #" + std::cerr << " not added in star #" << saa.m_center_point_index << " (basis dim = " << tangent_basis.dimension() # ifdef CGAL_TC_PROFILING - << " - " << t_one_fix.elapsed() << " s" + << " - " << t_one_fix.elapsed() << " s [recomputation = " + << recomp_timing << " s]" # endif << ")\n"; @@ -1049,7 +1051,8 @@ public: << saa.m_center_point_index << " (basis dim = " << tangent_basis.dimension() # ifdef CGAL_TC_PROFILING - << " - " << t_one_fix.elapsed() << " s" + << " - " << t_one_fix.elapsed() << " s [recomputation = " + << recomp_timing << " s]" # endif << ")\n"; //check_if_all_simplices_are_in_the_ambient_delaunay(); @@ -1197,7 +1200,7 @@ public: // Then save its simplices into "amb_dt_simplices" //------------------------------------------------------------------------- - typedef Regular_triangulation_euclidean_traits RT_Traits; + typedef Regular_triangulation_euclidean_traits RT_Traits; typedef Regular_triangulation< RT_Traits, Triangulation_data_structure< @@ -1241,15 +1244,15 @@ public: if (m_points.empty()) return true; - typedef Regular_triangulation_euclidean_traits RT_Traits; + typedef Regular_triangulation_euclidean_traits RT_Traits; typedef Regular_triangulation< RT_Traits, Triangulation_data_structure< typename RT_Traits::Dimension, Triangulation_vertex - > > RT; - typedef typename RT::Vertex_handle RT_VH; - typedef typename RT::Finite_full_cell_const_iterator FFC_it; + > > RT; + typedef typename RT::Vertex_handle RT_VH; + typedef typename RT::Finite_full_cell_const_iterator FFC_it; //------------------------------------------------------------------------- // Build the ambient Delaunay triangulation @@ -1343,6 +1346,8 @@ public: } }*/ + + p_simplices = &stars_simplices; } else @@ -1384,19 +1389,19 @@ private: class Compare_distance_to_ref_point { public: - Compare_distance_to_ref_point(Point const& ref, Kernel const& k) + Compare_distance_to_ref_point(Point const& ref, K const& k) : m_ref(ref), m_k(k) {} bool operator()(Point const& p1, Point const& p2) { - typename Kernel::Squared_distance_d sqdist = + typename K::Squared_distance_d sqdist = m_k.squared_distance_d_object(); return sqdist(p1, m_ref) < sqdist(p2, m_ref); } private: Point const& m_ref; - Kernel const& m_k; + K const& m_k; }; #ifdef CGAL_LINKED_WITH_TBB @@ -1473,6 +1478,9 @@ private: } #endif +#if defined(CGAL_TC_PROFILING) && defined(CGAL_TC_VERY_VERBOSE) + Wall_clock_timer t; +#endif int tangent_space_dim = tangent_basis_dim(i); Triangulation &local_tr = m_triangulations[i].construct_triangulation(tangent_space_dim); @@ -1480,16 +1488,13 @@ private: Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects - typename Kernel::Squared_distance_d k_sqdist = - m_k.squared_distance_d_object(); + typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); // Triangulation's traits functor & objects typename Tr_traits::Point_weight_d point_weight = local_tr_traits.point_weight_d_object(); typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object(); - typename Tr_traits::Compute_coordinate_d coord = - local_tr_traits.compute_coordinate_d_object(); //*************************************************** @@ -1649,7 +1654,12 @@ private: } } } - + +#if defined(CGAL_TC_PROFILING) && defined(CGAL_TC_VERY_VERBOSE) + std::cerr << " - triangulation construction: " << t.elapsed() << " s.\n"; + t.reset(); +#endif + #ifdef CGAL_TC_VERY_VERBOSE std::cerr << "Inserted " << num_inserted_points << " points / " << num_attempts_to_insert_points << " attemps to compute the star\n"; @@ -1665,6 +1675,10 @@ private: #else update_star__no_thickening_vectors(i); #endif + +#if defined(CGAL_TC_PROFILING) && defined(CGAL_TC_VERY_VERBOSE) + std::cerr << " - update_star: " << t.elapsed() << " s.\n"; +#endif } // Updates m_stars[i] directly from m_triangulations[i] @@ -1917,8 +1931,8 @@ next_face: Vector t(2, &tt[0], &tt[2]); // Normalize t1 and t2 - typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + typename K::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); @@ -1937,8 +1951,8 @@ next_face: Vector t2(3, &tt2[0], &tt2[3]); // Normalize t1 and t2 - typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + typename K::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); @@ -1974,19 +1988,19 @@ next_face: std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); // Kernel functors - typename Kernel::Construct_vector_d constr_vec = + typename K::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - typename Kernel::Squared_length_d sqlen = + typename K::Squared_length_d sqlen = m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Scalar_product_d scalar_pdct = + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Difference_of_vectors_d diff_vec = + typename K::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - //typename Kernel::Translated_point_d transl = + //typename K::Translated_point_d transl = // m_k.translated_point_d_object(); #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM @@ -2008,8 +2022,8 @@ next_face: for (int i = 0 ; i < m_ambient_dim ; ++i) { //const Point p = transl( - // m_points[nn_it->first], m_translations[nn_it->first]); - mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); + // points_for_pca[nn_it->first], m_translations[nn_it->first]); + mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i)); #ifdef CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE mat_points(j, i) += m_random_generator.get_double( -0.5*m_half_sparsity, 0.5*m_half_sparsity); @@ -2143,7 +2157,7 @@ next_face: Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) const { - typename Kernel::Construct_weighted_point_d k_constr_wp = + typename K::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); Weighted_point wp = k_constr_wp( @@ -2161,9 +2175,9 @@ next_face: const Tangent_space_basis &tsb, const Tr_traits &tr_traits) const { - typename Kernel::Translated_point_d k_transl = + typename K::Translated_point_d k_transl = m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = + typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object(); @@ -2189,9 +2203,9 @@ next_face: Tr_bare_point project_point(const Point &p, const Tangent_space_basis &tsb) const { - typename Kernel::Scalar_product_d scalar_pdct = + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Difference_of_points_d diff_points = + typename K::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); Vector v = diff_points(p, compute_perturbed_point(tsb.origin())); @@ -2224,9 +2238,9 @@ next_face: const Tangent_space_basis &tsb, const Tr_traits &tr_traits) const { - typename Kernel::Point_drop_weight_d k_drop_w = + typename K::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object(); - typename Kernel::Point_weight_d k_point_weight = + typename K::Point_weight_d k_point_weight = m_k.point_weight_d_object(); return project_point_and_compute_weight( k_drop_w(wp), k_point_weight(wp), tsb, tr_traits); @@ -2237,13 +2251,13 @@ next_face: const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); - typename Kernel::Scalar_product_d scalar_pdct = + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Difference_of_points_d diff_points = + typename K::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); - typename Kernel::Compute_coordinate_d coord = + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - typename Kernel::Construct_cartesian_const_iterator_d ccci = + typename K::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); Point origin = compute_perturbed_point(tsb.origin()); @@ -2333,11 +2347,11 @@ next_face: double compute_simplex_fatness(IndexRange const& simplex) const { // Kernel functors - typename Kernel::Compute_coordinate_d coord = + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - typename Kernel::Squared_distance_d sqdist = + typename K::Squared_distance_d sqdist = m_k.squared_distance_d_object(); - typename Kernel::Difference_of_points_d diff_pts = + typename K::Difference_of_points_d diff_pts = m_k.difference_of_points_d_object(); typename Tr_traits::Difference_of_points_d tr_diff_pts = @@ -2551,7 +2565,7 @@ next_face: // Perturb the position? #ifdef CGAL_TC_PERTURB_POSITION # ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = + typename K::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); CGAL::Random_points_in_ball_d tr_point_in_ball_generator( @@ -2572,11 +2586,11 @@ next_face: m_triangulations[point_idx].tr().geom_traits(); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); - typename Kernel::Translated_point_d k_transl = + typename K::Translated_point_d k_transl = m_k.translated_point_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = + typename K::Construct_vector_d k_constr_vec = m_k.construct_vector_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = + typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); CGAL::Random_points_in_ball_d @@ -2832,7 +2846,7 @@ next_face: const int N = (m_intrinsic_dim == 1 ? 2 : 1); // Kernel functors - typename Kernel::Compute_coordinate_d coord = + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); int num_coords = min(m_ambient_dim, 3); @@ -2921,19 +2935,19 @@ next_face: CGAL_assertion(std::find(m_stars[q_idx].begin(), m_stars[q_idx].end(), inc_s_minus_q) == m_stars[q_idx].end()); - typename Kernel::Point_drop_weight_d k_drop_w = + typename K::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object(); - typename Kernel::Translated_point_d k_transl = + typename K::Translated_point_d k_transl = m_k.translated_point_d_object(); - typename Kernel::Squared_distance_d k_sqdist = + typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); - typename Kernel::Difference_of_points_d k_diff_pts = + typename K::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - typename Kernel::Scalar_product_d k_scalar_pdct = + typename K::Scalar_product_d k_scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Construct_weighted_point_d k_constr_wp = + typename K::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); - typename Kernel::Power_distance_d k_power_dist = + typename K::Power_distance_d k_power_dist = m_k.power_distance_d_object(); const Tr_traits &q_tr_traits = m_triangulations[q_idx].tr().geom_traits(); @@ -3100,9 +3114,9 @@ next_face: // If co-intrinsic dimension = 1, let's compare normals /*if (m_ambient_dim - m_intrinsic_dim == 1) { - typename Kernel::Scaled_vector_d k_scaled_vec = + typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Squared_length_d k_sqlen = + typename K::Squared_length_d k_sqlen = m_k.squared_length_d_object(); Vector pq = k_diff_pts( compute_perturbed_point(q_idx), compute_perturbed_point(p_idx)); @@ -3189,8 +3203,8 @@ next_face: // CJTODO TEMP ==================== /*{ - typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Point_weight_d k_weight = m_k.point_weight_d_object(); + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + typename K::Point_weight_d k_weight = m_k.point_weight_d_object(); Weighted_point C = k_constr_wp( k_transl(k_drop_w(global_Cp), scaled_vec(k_diff_pts(k_drop_w(global_Cq), k_drop_w(global_Cp)), min_a)), k_sqdist(k_transl(k_drop_w(global_Cp), scaled_vec(k_diff_pts(k_drop_w(global_Cq), k_drop_w(global_Cp)), min_a)), pt_p)); @@ -3284,13 +3298,13 @@ next_face: // CJTODO TEMP /*else if (m_ambient_dim - m_intrinsic_dim == 1) { - typename Kernel::Difference_of_points_d k_diff_pts = + typename K::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = + typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Squared_length_d k_sqlen = + typename K::Squared_length_d k_sqlen = m_k.squared_length_d_object(); - typename Kernel::Scalar_product_d k_scalar_pdct = + typename K::Scalar_product_d k_scalar_pdct = m_k.scalar_product_d_object(); Vector pq = k_diff_pts( compute_perturbed_point(*it_point_idx), compute_perturbed_point(tr_index)); @@ -3336,7 +3350,7 @@ next_face: typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object(); - typename Kernel::Compute_coordinate_d k_coord = + typename K::Compute_coordinate_d k_coord = m_k.compute_coordinate_d_object(); std::size_t card_P = P.size(); @@ -3514,9 +3528,9 @@ next_face: // Fv: Voronoi k-face // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) - typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); + typename K::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); Point center_pt = compute_perturbed_point(center_pt_index); int const ambient_dim = m_k.point_dimension_d_object()(center_pt); @@ -4057,7 +4071,7 @@ public: } private: - const Kernel m_k; + const K m_k; const int m_intrinsic_dim; const double m_half_sparsity; const double m_sq_half_sparsity; From f00c925ccc66e2f6cb19fb692f2d849c4980304f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 15:37:07 +0100 Subject: [PATCH 395/487] Test a kind of "Mesh_d" algorithm - first draft --- .../Tangential_complex/CMakeLists.txt | 4 + .../Tangential_complex/benchmark_mesh_d.cpp | 412 ++++++++++++++++++ .../Tangential_complex/benchmark_script.txt | 207 +++++---- .../Tangential_complex/Simplicial_complex.h | 16 +- .../include/CGAL/Tangential_complex/config.h | 12 +- .../CGAL/Tangential_complex/utilities.h | 9 - .../Tangential_complex/testing_utilities.h | 70 ++- 7 files changed, 615 insertions(+), 115 deletions(-) create mode 100644 Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp diff --git a/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt index 7155f246c2b..56b513551fc 100644 --- a/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt @@ -66,6 +66,10 @@ if ( CGAL_FOUND ) set (SOURCE_FILES "benchmark_tc.cpp") ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES) create_single_source_cgal_program( ${SOURCE_FILES} ) + + set (SOURCE_FILES "benchmark_mesh_d.cpp") + ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES) + create_single_source_cgal_program( ${SOURCE_FILES} ) else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp new file mode 100644 index 00000000000..8ff7c0d0d67 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -0,0 +1,412 @@ +//#undef CGAL_LINKED_WITH_TBB // CJTODO TEMP + +// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB +// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/) +#ifdef _DEBUG +# define TBB_USE_THREADING_TOOL +#endif + + +#include +#include +#include +#include +#include + +#include "../../test/Tangential_complex/testing_utilities.h" + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif + +using namespace CGAL::Tangential_complex_; + +const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt"; + +typedef CGAL::Epick_d Kernel; +typedef Kernel::FT FT; +typedef Kernel::Point_d Point; +typedef CGAL::Mesh_d< + Kernel, CGAL::Dynamic_dimension_tag, + CGAL::Parallel_tag> Mesh; + +//#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY +//#define MESH_D_INPUT_STRIDES 10 // only take one point every MESH_D_INPUT_STRIDES points +//#define MESH_D_NO_EXPORT + + +template +bool export_to_off( + Mesh const& mesh, + std::string const& input_name_stripped, + std::string const& suffix, + Indexed_simplex_range const *p_simpl_to_color_in_red = NULL, + Indexed_simplex_range const *p_simpl_to_color_in_green = NULL, + Indexed_simplex_range const *p_simpl_to_color_in_blue = NULL) +{ +#ifdef MESH_D_NO_EXPORT + return true; +#endif + if (mesh.intrinsic_dimension() <= 3) + { + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" + << mesh.intrinsic_dimension() << "_in_R" + << mesh.ambient_dimension() << "_" + << mesh.number_of_vertices() << "v" + << suffix << ".off"; + + std::ofstream off_stream(output_filename.str().c_str()); + + mesh.export_to_off( + off_stream, + p_simpl_to_color_in_red, + p_simpl_to_color_in_green, + p_simpl_to_color_in_blue); + return true; + } + + return false; +} + + +void make_mesh( + std::vector &points, + int intrinsic_dim, + bool sparsify = true, + double sparsity = 0.01, + const char *input_name = "mesh") +{ + Kernel k; + + //=========================================================================== + // Init + //=========================================================================== + Wall_clock_timer t; + + // Get input_name_stripped + std::string input_name_stripped(input_name); + size_t slash_index = input_name_stripped.find_last_of('/'); + if (slash_index == std::string::npos) + slash_index = input_name_stripped.find_last_of('\\'); + if (slash_index == std::string::npos) + slash_index = 0; + else + ++slash_index; + input_name_stripped = input_name_stripped.substr( + slash_index, input_name_stripped.find_last_of('.') - slash_index); + + int ambient_dim = k.point_dimension_d_object()(*points.begin()); + +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + std::vector points_not_sparse = points; +#endif + + //=========================================================================== + // Sparsify point set if requested + //=========================================================================== + if (sparsify) + { + std::size_t num_points_before = points.size(); + points = sparsify_point_set(k, points, sparsity*sparsity); + std::cerr << "Number of points before/after sparsification: " + << num_points_before << " / " << points.size() << std::endl; + } + + //=========================================================================== + // Compute Tangential Complex + //=========================================================================== + +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, + points_not_sparse.begin(), points_not_sparse.end(), k); +#else + Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, k); +#endif + + double init_time = t.elapsed(); t.reset(); + + std::vector > uncertain_simplices; + mesh.compute_mesh(&uncertain_simplices); + double computation_time = t.elapsed(); t.reset(); + + mesh.display_stats(); + + //========================================================================= + // Export to OFF + //========================================================================= + t.reset(); + bool exported = export_to_off( + mesh, input_name_stripped, "", &uncertain_simplices); + double export_time = (exported ? t.elapsed() : -1); + t.reset(); + + //=========================================================================== + // Is the result a pure pseudomanifold? + //=========================================================================== + std::size_t num_wrong_dim_simplices, + num_wrong_number_of_cofaces, + num_unconnected_stars; + std::set > wrong_dim_simplices; + std::set > wrong_number_of_cofaces_simplices; + std::set > unconnected_stars_simplices; + bool is_pure_pseudomanifold = mesh.complex().is_pure_pseudomanifold( + intrinsic_dim, mesh.number_of_vertices(), false, 1, + &num_wrong_dim_simplices, &num_wrong_number_of_cofaces, + &num_unconnected_stars, + &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, + &unconnected_stars_simplices); + + // Stats about the simplices + mesh.complex().display_stats(); + + //=========================================================================== + // Display info + //=========================================================================== + + std::cerr << std::endl + << "================================================" << std::endl + << "Number of vertices: " << mesh.number_of_vertices() << std::endl + //<< "Pure pseudomanifold: " << (is_pure_pseudomanifold ? "YES" : "NO") << std::endl + << "Computation times (seconds): " << std::endl + << " * Mesh: " << init_time + computation_time << std::endl + << " - Init + kd-tree = " << init_time << std::endl + << " - Mesh computation = " << computation_time << std::endl + //<< " * Export to OFF : " << export_before_time << std::endl + << "================================================" << std::endl + << std::endl; +} + +int main() +{ + CGAL::set_error_behaviour(CGAL::ABORT); + +#ifdef CGAL_LINKED_WITH_TBB +# ifdef _DEBUG + int num_threads = 1; +# else + int num_threads = 8; +# endif +#endif + + unsigned int seed = static_cast(time(NULL)); + CGAL::default_random = CGAL::Random(seed); + std::cerr << "Random seed = " << seed << std::endl; + + std::ifstream script_file; + script_file.open(BENCHMARK_SCRIPT_FILENAME); + // Script? + // Script file format: each line gives + // - Filename (point set) or "generate_XXX" (point set generation) + // - Ambient dim + // - Intrinsic dim + // - Number of iterations with these parameters + if (script_file.is_open()) + { + int i = 1; +#ifdef CGAL_LINKED_WITH_TBB +# ifdef BENCHMARK_WITH_1_TO_MAX_THREADS + for(num_threads = 1 ; + num_threads <= tbb::task_scheduler_init::default_num_threads() ; + ++num_threads) +# endif +#endif + { +#ifdef CGAL_LINKED_WITH_TBB + tbb::task_scheduler_init init( + num_threads > 0 ? num_threads : tbb::task_scheduler_init::automatic); +#endif + + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME + << "' found." << std::endl; + script_file.seekg(0); + while (script_file.good()) + { + std::string line; + std::getline(script_file, line); + if (line.size() > 1 && line[0] != '#') + { + boost::replace_all(line, "\t", " "); + boost::trim_all(line); + std::cerr << std::endl << std::endl; + std::cerr << "*****************************************" << std::endl; + std::cerr << "******* " << line << std::endl; + std::cerr << "*****************************************" << std::endl; + std::stringstream sstr(line); + + std::string input; + std::string param1; + std::string param2; + std::string param3; + std::size_t num_points; + int ambient_dim; + int intrinsic_dim; + char sparsify; + double sparsity; + char perturb, add_high_dim_simpl, collapse; + double time_limit_for_perturb; + int num_iteration; + sstr >> input; + sstr >> param1; + sstr >> param2; + sstr >> param3; + sstr >> num_points; + sstr >> ambient_dim; + sstr >> intrinsic_dim; + sstr >> sparsify; + sstr >> sparsity; + sstr >> perturb; + sstr >> add_high_dim_simpl; + sstr >> collapse; + sstr >> time_limit_for_perturb; + sstr >> num_iteration; + + for (int j = 0 ; j < num_iteration ; ++j) + { + std::string input_stripped = input; + size_t slash_index = input_stripped.find_last_of('/'); + if (slash_index == std::string::npos) + slash_index = input_stripped.find_last_of('\\'); + if (slash_index == std::string::npos) + slash_index = 0; + else + ++slash_index; + input_stripped = input_stripped.substr( + slash_index, input_stripped.find_last_of('.') - slash_index); + + std::cerr << std::endl << "Mesh #" << i << "..." << std::endl; + +#ifdef CGAL_MESH_D_PROFILING + Wall_clock_timer t_gen; +#endif + + std::vector points; + + if (input == "generate_moment_curve") + { + points = generate_points_on_moment_curve( + num_points, ambient_dim, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else if (input == "generate_plane") + { + points = generate_points_on_plane( + num_points, intrinsic_dim, ambient_dim); + } + else if (input == "generate_sphere_d") + { + points = generate_points_on_sphere_d( + num_points, ambient_dim, + std::atof(param1.c_str()), // radius + std::atof(param2.c_str())); // radius_noise_percentage + } + else if (input == "generate_two_spheres_d") + { + points = generate_points_on_two_spheres_d( + num_points, ambient_dim, + std::atof(param1.c_str()), + std::atof(param2.c_str()), + std::atof(param3.c_str())); + } + else if (input == "generate_3sphere_and_circle_d") + { + CGAL_assertion(intrinsic_dim == 3); + CGAL_assertion(ambient_dim == 5); + points = generate_points_on_3sphere_and_circle( + num_points, + std::atof(param1.c_str())); + } + else if (input == "generate_torus_3D") + { + points = generate_points_on_torus_3D( + num_points, + std::atof(param1.c_str()), + std::atof(param2.c_str()), + param3 == "Y"); + } + else if (input == "generate_torus_d") + { + points = generate_points_on_torus_d( + num_points, + intrinsic_dim, + param1 == "Y", // uniform + std::atof(param2.c_str())); // radius_noise_percentage + } + else if (input == "generate_klein_bottle_3D") + { + points = generate_points_on_klein_bottle_3D( + num_points, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else if (input == "generate_klein_bottle_4D") + { + points = generate_points_on_klein_bottle_4D( + num_points, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else if (input == "generate_klein_bottle_variant_5D") + { + points = generate_points_on_klein_bottle_variant_5D( + num_points, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else + { + load_points_from_file( + input, std::back_inserter(points)/*, 600*/); + } + +#ifdef CGAL_MESH_D_PROFILING + std::cerr << "Point set generated/loaded in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif + + if (!points.empty()) + { +#if defined(MESH_D_INPUT_STRIDES) && MESH_D_INPUT_STRIDES > 1 + auto p = points | boost::adaptors::strided(MESH_D_INPUT_STRIDES); // CJTODO C++11 (auto) + std::vector points(p.begin(), p.end()); + std::cerr << "****************************************\n" + << "WARNING: taking 1 point every " << MESH_D_INPUT_STRIDES + << " points.\n" + << "****************************************\n"; +#endif + make_mesh( + points, intrinsic_dim, sparsify == 'Y', sparsity, + input.c_str()); + + std::cerr << "Mesh #" << i++ << " done." << std::endl; + std::cerr << std::endl << "---------------------------------" + << std::endl << std::endl; + } + else + { + std::cerr << "Mesh #" << i++ << ": no points loaded." << std::endl; + } + } + } + } + script_file.seekg(0); + script_file.clear(); + } + + script_file.close(); + } + // Or not script? + else + { + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found." << std::endl; + } + + system("pause"); + return 0; +} diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 7e243e29c03..556d18dbb2a 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -1,109 +1,136 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- -# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS +# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSIFY SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- #---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ -#generate_sphere_d 1 1 - 50 2 1 0.005 N Y N 3 1 #OK -#generate_torus_d N - - 15 2 1 0.05 N Y N 10 1 -#generate_sphere_d 0.302 3 - 50 3 2 0.005 N Y N 60 1 #OK -#generate_sphere_d 0.302 2 - 300 2 1 0.005 N Y N 60 1 -#generate_torus_3D 2 1 N 200 3 2 0.05 N Y N 600 1 #OK => tetraedra only -#data/fandisk.txt - - - 0 3 2 0.005 Y Y N 5 1 -generate_torus_d N 1 - 50 4 2 0.05 N Y N 3 1 #NOT OK: various errors -#generate_torus_d Y 1 - 2500 4 2 0.05 N Y N 3 1 #NOT OK -#generate_torus_d N - - 30 6 3 0.05 N Y N 300 1 -#generate_moment_curve 0 1 - 10 3 1 0.005 N Y N 60 1 -#generate_two_spheres_d 3 4 - 500 3 2 0.05 N Y N 10 1 #OK -#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N Y N 60 1 +#generate_sphere_d 1 0 - 8 2 1 Y 0.005 N Y N 3 1 #No noise => OK: 6 2d with a perturb sometimes +#generate_sphere_d 1 0 - 50 2 1 Y 0.005 N Y N 3 1 #No noise => OK: 49 1d +#generate_sphere_d 1 1 - 50 2 1 Y 0.005 N Y N 3 1 #Noise => OK: 45 2d + 3 3d +#generate_torus_d N - - 15 2 1 Y 0.05 N Y N 10 1 +#generate_sphere_d 0.302 0 - 8 3 2 Y 0.005 N Y N 60 1 #No noise => OK: 7 3d with a perturb sometimes +#generate_sphere_d 0.302 0 - 50 3 2 Y 0.005 N Y N 60 1 #No noise => no inconsitencies +#generate_sphere_d 0.302 3 - 50 3 2 Y 0.005 N Y N 60 1 #Noise => OK: 90 2d + 3 3d +#generate_sphere_d 1 1 - 500 4 3 Y 0.005 N Y N 60 1 #Noise 1% => OK: 3113 3d + 35 4d +#generate_sphere_d 1 2 - 500 4 3 Y 0.005 N Y N 60 1 #Noise 2% => OK: 2969 3d + 91 4d +#generate_sphere_d 1 2 - 5000 4 3 Y 0.005 N Y N 60 1 #Noise 2% => OK: 27905 3d + 2485 4d +#generate_sphere_d 0.302 2 - 300 2 1 Y 0.005 N Y N 60 1 +#generate_torus_3D 2 1 N 200 3 2 Y 0.05 N Y N 600 1 #OK: 1048 3d ~170s +#generate_torus_3D 2 1 N 2000 3 2 Y 0.05 N Y N 600 1 #OK: 3545 2d + 27 3d ~35s +#generate_torus_d N 1 - 50 4 2 Y 0.05 N Y N 3 1 #OK: 431 4d +#generate_torus_d N 1 - 500 4 2 Y 0.05 N Y N 3 1 #OK: 881 2d + 37 3d +#generate_torus_d Y 1 - 250 4 2 Y 0.05 N Y N 3 1 #OK: 80 d2 + 185 d3 +#generate_torus_d N - - 50 6 3 Y 0.05 Y Y N 10 1 # +#generate_torus_d Y - - 700 6 3 Y 0.05 Y Y N 100 1 #Grid +#generate_torus_d N - - 50000 6 3 Y 0.05 Y Y N 0 1 #Too long... +#generate_moment_curve 0 1 - 10 3 1 Y 0.005 N Y N 60 1 +#generate_two_spheres_d 3 4 - 500 3 2 Y 0.05 N Y N 10 1 #OK: 320 2d + 1167 3d +#generate_klein_bottle_4D 40 15 - 500 4 2 Y 0.2 N Y N 60 1 #OK: 901 d2 + 50 d3 + 1 d4 +#data/SO3_10000.txt - - - 0 9 3 Y 0.05 Y Y N 300 1 #Too long. Be careful with the memory consumption! +#data/buddha_100kv.txt - - - 0 3 2 Y 0.005 Y Y N 120 1 #Too long... +#data/fandisk.txt - - - 0 3 2 Y 0.005 Y Y N 5 1 #NOT OK: Tq & V do not intersect #---------------------------------------------------------------- Fixed-alpha TC tests ------------------------------------------------------------------------ -#generate_sphere_d 0.302 - - 70 2 1 0.005 N N N 60 1 -#generate_sphere_d 0.304 0 - 100 3 2 0.05 N N N 60 1 -#generate_sphere_d 3 0 - 100 4 3 0.05 N N N 60 1 -#generate_sphere_d 3 0 - 1000 5 4 0.05 N N N 60 1 -#generate_two_spheres_d 3 4 - 1000 3 2 0.05 N N N 10 1 -#generate_two_spheres_d 3 10 - 1000 4 3 0.05 N N N 10 1 -#generate_two_spheres_d 3 10 - 2000 5 4 0.05 N N N 10 1 -#generate_3sphere_and_circle_d 3 - - 100000 5 3 0.05 N N N 7000 1 -#generate_plane - - - 100 4 3 0.005 N N N 3000 1 -#generate_plane - - - 10 5 4 0.005 N N N 3000 1 -#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N N 60 1 -#generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N N 60 1 -#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N N N 60 1 #Takes forever -#generate_torus_3D 2 1 Y 150 3 2 0.05 N N N 600 1 -#generate_torus_3D 2 1 N 100000 3 2 0.55 N N N 600 1 -#generate_torus_d N - - 18 2 1 0.01 N N N 30 1 -#generate_torus_d N - - 50000 2 1 0.7 N N N 30 1 -#generate_torus_d Y - - 2 2 1 0 N N N 30 1 -#generate_torus_d Y - - 15 4 2 0.05 N N N 30 1 -#generate_torus_d N 0 - 150 4 2 0.05 N N N 10 1 -#generate_torus_d N - - 20000 4 2 1.0 N N N 30 1 -#generate_torus_d Y 0 - 5000 6 3 0.05 N N N 300 1 -#generate_torus_d N - - 20000 6 3 0.05 N N N 60 1 -#generate_torus_d N - - 100000 6 3 0.05 N N N 3000 1 -#generate_torus_d N - - 1000000 6 3 0.3 N N N 3000 1 -#generate_torus_d Y - - 1000 8 4 0.05 N N N 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.1 N N N 60 1 +#generate_sphere_d 0.302 - - 70 2 1 Y 0.005 N N N 60 1 +#generate_sphere_d 0.304 0 - 100 3 2 Y 0.05 N N N 60 1 +#generate_sphere_d 3 0 - 100 4 3 Y 0.05 N N N 60 1 +#generate_sphere_d 3 0 - 1000 5 4 Y 0.05 N N N 60 1 +#generate_two_spheres_d 3 4 - 1000 3 2 Y 0.05 N N N 10 1 +#generate_two_spheres_d 3 10 - 1000 4 3 Y 0.05 N N N 10 1 +#generate_two_spheres_d 3 10 - 2000 5 4 Y 0.05 N N N 10 1 +#generate_3sphere_and_circle_d 3 - - 100000 5 3 Y 0.05 N N N 7000 1 +#generate_plane - - - 100 4 3 Y 0.005 N N N 3000 1 +#generate_plane - - - 10 5 4 Y 0.005 N N N 3000 1 +#generate_klein_bottle_4D 40 15 - 500 4 2 Y 0.2 N N N 60 1 +#generate_klein_bottle_4D 40 15 - 2000 4 2 Y 0.2 N N N 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 Y 0.2 N N N 60 1 #Takes forever +#generate_torus_3D 2 1 Y 150 3 2 Y 0.05 N N N 600 1 +#generate_torus_3D 2 1 N 100000 3 2 Y 0.55 N N N 600 1 +#generate_torus_d N - - 18 2 1 Y 0.01 N N N 30 1 +#generate_torus_d N - - 50000 2 1 Y 0.7 N N N 30 1 +#generate_torus_d Y - - 2 2 1 N 0.01 N N N 30 1 +#generate_torus_d Y - - 15 4 2 Y 0.05 N N N 30 1 +#generate_torus_d N 0 - 150 4 2 Y 0.05 N N N 10 1 +#generate_torus_d N - - 20000 4 2 Y 1.0 N N N 30 1 +#generate_torus_d Y 0 - 5000 6 3 Y 0.05 N N N 300 1 +#generate_torus_d N - - 20000 6 3 Y 0.05 N N N 60 1 +#generate_torus_d N - - 100000 6 3 Y 0.05 N N N 3000 1 +#generate_torus_d N - - 1000000 6 3 Y 0.3 N N N 3000 1 +#generate_torus_d Y - - 1000 8 4 Y 0.05 N N N 60 1 +#data/SO3_10000.txt - - - 0 9 3 Y 0.1 N N N 60 1 #---------------------------------------------------------- Spatial search benchmarking -------------------------------------------------------------- -#generate_torus_3D 2 1 Y 10000 3 2 0 Y N N 600 1 -#data/buddha_100kv.txt - - - 0 3 2 0 N Y N 120 1 -#generate_torus_d N - - 10000 30 15 0 Y N N 3600 1 -#generate_torus_d N - - 100000 12 6 0 Y N N 3600 1 -#data/SO3_50000.txt - - - 0 9 3 0 Y N N 60 1 -#data/Cy8.txt - - - 0 24 2 0 N Y N 60 1 -#generate_sphere_d 0.5 - - 10000 2 1 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 3 2 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 4 3 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 5 4 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 6 5 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 7 6 0 N N Y 60 1 +#generate_torus_3D 2 1 Y 10000 3 2 N 0 Y N N 600 1 +#data/buddha_100kv.txt - - - 0 3 2 N 0 N Y N 120 1 +#generate_torus_d N - - 10000 30 15 N 0 Y N N 3600 1 +#generate_torus_d N - - 100000 12 6 N 0 Y N N 3600 1 +#data/SO3_50000.txt - - - 0 9 3 N 0 Y N N 60 1 +#data/Cy8.txt - - - 0 24 2 N 0 N Y N 60 1 +#generate_sphere_d 0.5 - - 10000 2 1 N 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 3 2 N 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 4 3 N 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 5 4 N 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 6 5 N 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 7 6 N 0 N N Y 60 1 #---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- -#generate_sphere_d 4 - - 20 3 2 0.05 N Y N 60 1 -#generate_sphere_d 3 - - 70 3 2 0.05 N Y N 60 1 -#generate_sphere_d 3 - - 1000 3 2 0.05 N Y N 60 1 -#generate_sphere_d 3 - - 70 4 3 0.05 N Y N 60 1 -#generate_sphere_d 3 - - 70 5 4 0.05 N Y N 60 1 -#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 N Y N 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.7 N Y N 60 1 -#generate_moment_curve 0 1 - 30 3 1 0.005 N Y N 60 1 +#generate_sphere_d 4 - - 20 3 2 Y 0.05 N N N 60 1 +#generate_sphere_d 3 - - 70 3 2 Y 0.05 N N N 60 1 +#generate_sphere_d 3 - - 1000 3 2 Y 0.05 N N N 60 1 +#generate_sphere_d 3 - - 70 4 3 Y 0.05 N N N 60 1 +#generate_sphere_d 3 - - 70 5 4 Y 0.05 N N N 60 1 +#generate_klein_bottle_variant_5D 4 3 - 70 5 2 Y 0.05 N N N 60 1 +#data/SO3_10000.txt - - - 0 9 3 Y 0.7 N N N 60 1 +#generate_moment_curve 0 1 - 30 3 1 Y 0.005 N N N 60 1 #------------------------------------------------------------------ From files -------------------------------------------------------------------------- -#data/SO3_50000.txt - - - 0 9 3 0.05 Y Y N 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.05 Y N N 60 1 -#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 N Y N 3000 1 -#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 N Y N 3000 1 -#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 N Y N 3000 1 -#data/Cy8.txt - - - 0 24 2 0.1 N Y N 60 1 -#data/Kl.txt - - - 0 5 2 0.05 N Y N 60 1 -#data/S3.txt - - - 0 4 3 0.05 N Y N 60 1 +#data/SO3_50000.txt - - - 0 9 3 Y 0.05 Y Y N 60 1 +#data/SO3_10000.txt - - - 0 9 3 Y 0.05 Y N N 60 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 Y 0.05 N Y N 3000 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 Y 0.05 N Y N 3000 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 Y 0.05 N Y N 3000 1 +#data/Cy8.txt - - - 0 24 2 Y 0.1 N Y N 60 1 +#data/Kl.txt - - - 0 5 2 Y 0.05 N Y N 60 1 +#data/S3.txt - - - 0 4 3 Y 0.05 N Y N 60 1 + +data/Alvarez_variete_k2_D4_29700p.txt - - - 0 4 2 Y 0.01 Y N N 36000 1 +#data/Alvarez_variete_k2_D4_300k_random.txt - - - 0 4 2 Y 0.01 Y N N 36000 1 + +#data/Alvarez_variete_k2_D4_29700p.txt - - - 0 4 2 Y 0.01 Y N N 500000 1 +#data/Alvarez_variete_k2_D4_297k.txt - - - 0 4 2 Y 0.001 Y N N 500000 1 +#data/Alvarez_variete_k2_D4_297k.txt - - - 0 4 2 Y 0.5 Y N N 500000 1 +#data/Alvarez_variete_k2_D4_300k_random.txt - - - 0 4 2 Y 0.001 Y N N 500000 1 +#data/Alvarez_variete_k2_D4_300k_random.txt - - - 0 4 2 Y 0.2 Y N N 500000 1 + +# With pre-computed tangent spaces +#data/test.pwt - - - 0 4 2 Y 0.01 N N N 500000 1 +#data/Alvarez_variete_k2_D4_30000p.txt - - - 0 4 2 Y 0.01 Y N N 500000 1 +#data/Alvarez_variete_k2_D4_30000p_with_TSB.pwt - - - 0 4 2 N 0.01 Y N N 500000 1 #---------------------------------------------------------------------- 3D meshes ----------------------------------------------------------------------- -#data/buddha_100kv.txt - - - 0 3 2 0.005 N Y N 120 1 -#data/fandisk.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/fertility.txt - - - 0 3 2 0.4 N Y N 60 1 -#data/bunny.txt - - - 0 3 2 0.5 N Y N 60 1 -#data/blob.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/3holes.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/785_hand_2500v.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/785_hand_50kv.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/bumpy_sphere.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/buddha_100kv.txt - - - 0 3 2 Y 0.005 N Y N 120 1 +#data/fandisk.txt - - - 0 3 2 Y 0.01 N Y N 60 1 +#data/fertility.txt - - - 0 3 2 Y 0.4 N Y N 60 1 +#data/bunny.txt - - - 0 3 2 Y 0.5 Y N N 60 1 +#data/blob.txt - - - 0 3 2 Y 0.01 N Y N 60 1 +#data/3holes.txt - - - 0 3 2 Y 0.01 N Y N 60 1 +#data/785_hand_2500v.txt - - - 0 3 2 Y 0.01 N Y N 60 1 +#data/785_hand_50kv.txt - - - 0 3 2 Y 0.01 N Y N 60 1 +#data/bumpy_sphere.txt - - - 0 3 2 Y 0.01 N Y N 60 1 #----------------------------------------------------------- Generated point sets ----------------------------------------------------------------------- -#generate_sphere_d 3 - - 4 3 2 0.05 N Y N 3000 1 -#generate_sphere_d 3 - - 30000 2 1 0.005 N Y N 3000 1 -#generate_sphere_d 3 - - 30000 3 2 0.005 N Y N 3000 1 -#generate_sphere_d 3 - - 30000 4 3 0.05 N Y N 3000 1 -#generate_sphere_d 3 0 - 3000 3 2 0.005 N Y N 60 1 -#generate_sphere_d 3 4 - 3000 3 2 0.005 N Y N 60 1 -#generate_sphere_d 3 7 - 3000 3 2 0.005 N Y N 60 1 -#generate_plane - - - 30000 3 2 0.005 N Y N 3000 1 -#generate_moment_curve 0 1 - 30000 6 1 0.005 N Y N 60 1 -#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 N Y N 60 1 -#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 N Y N 60 1 -#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever +#generate_sphere_d 3 - - 4 3 2 Y 0.05 N N N 3000 1 +#generate_sphere_d 3 - - 30000 2 1 Y 0.005 N N N 3000 1 +#generate_sphere_d 3 - - 30000 3 2 Y 0.005 N N N 3000 1 +#generate_sphere_d 3 - - 30000 4 3 Y 0.05 N N N 3000 1 +#generate_sphere_d 3 0 - 300 3 2 Y 0.005 N N N 60 1 +#generate_sphere_d 3 4 - 3000 3 2 Y 0.005 N N N 60 1 +#generate_sphere_d 3 7 - 3000 3 2 Y 0.005 N N N 60 1 +#generate_plane - - - 30000 3 2 Y 0.005 N N N 3000 1 +#generate_moment_curve 0 1 - 30000 6 1 Y 0.005 N N N 60 1 +#generate_klein_bottle_4D 4 3 - 1000 4 2 Y 0.01 N N N 3 1 +#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 Y 0.05 N N N 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 Y 0.2 N N N 60 1 #Takes forever #----------------------------------------------------------- Performance testing ------------------------------------------------------------------------ # TC: 5.55 / 1st fix step : 0.2 -#data/fertility.txt - - - 0 3 2 0.1 N Y N 100 1 \ No newline at end of file +#data/fertility.txt - - - 0 3 2 Y 0.1 N Y N 100 1 \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index ecdea36ce3a..199691c0a64 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -244,7 +244,7 @@ public: bool exit_at_the_first_problem = false, int verbose_level = 0, std::size_t *p_num_wrong_dim_simplices = NULL, - std::size_t *p_num_wrong_number_of_cofaces = NULL) + std::size_t *p_num_wrong_number_of_cofaces = NULL) const { typedef std::set K_1_face; typedef std::map Cofaces_map; @@ -333,7 +333,7 @@ public: std::size_t *p_num_unconnected_stars = NULL, Simplex_range *p_wrong_dim_simplices = NULL, Simplex_range *p_wrong_number_of_cofaces_simplices = NULL, - Simplex_range *p_unconnected_stars_simplices = NULL) + Simplex_range *p_unconnected_stars_simplices = NULL) const { // If simplex_dim == 1, we do not need to check if stars are connected if (simplex_dim == 1) @@ -382,7 +382,7 @@ public: } } - // Now, for each star, with have a vector of its d-simplices + // Now, for each star, we have a vector of its d-simplices // i.e. one index for each d-simplex // Boost Graph only deals with indexes, so we also need indexes for the // (d-1)-simplices @@ -450,9 +450,13 @@ public: } // What is left is to check the connexity - std::vector components(boost::num_vertices(adj_graph)); - bool is_connected = - (boost::connected_components(adj_graph, &components[0]) == 1); + bool is_connected = true; + if (boost::num_vertices(adj_graph) > 0) + { + std::vector components(boost::num_vertices(adj_graph)); + is_connected = + (boost::connected_components(adj_graph, &components[0]) == 1); + } if (!is_connected) { diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 3f01cde07a4..f9def39e883 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -32,17 +32,16 @@ //=========================== Alpha-TC or not? ================================ -#define CGAL_ALPHA_TC +//#define CGAL_ALPHA_TC //#define CGAL_USE_A_FIXED_ALPHA const double CGAL_TC_ALPHA_VALUE = 0.3; //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE -#define CGAL_TC_VERY_VERBOSE -#define CGAL_TC_PERFORM_EXTRA_CHECKS -//#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -//#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +//#define CGAL_TC_VERY_VERBOSE +//#define CGAL_TC_PERFORM_EXTRA_CHECKS +#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES // Solving inconsistencies: only perturb the vertex, the simplex or more? //#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY @@ -55,6 +54,8 @@ #define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) //#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) +#define CGAL_MESH_D_PROFILING +#define CGAL_MESH_D_VERBOSE //========================= Strategy ========================================== #define CGAL_TC_NANOFLANN_IS_AVAILABLE @@ -76,5 +77,6 @@ // PCA will use BASE_VALUE_FOR_PCA^intrinsic_dim points const std::size_t BASE_VALUE_FOR_PCA = 5; +const unsigned int BASE_VALUE_FOR_ALPHA_TC_NEIGHBORHOOD = 5; #endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index ec95a318317..e1472ae8d95 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include #include @@ -35,13 +33,6 @@ #include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) -// choose exact integral type for QP solver -// (Gmpzf is not thread-safe) -#include -typedef CGAL::MP_Float ET; -//#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 - - namespace CGAL { namespace Tangential_complex_ { diff --git a/Tangential_complex/test/Tangential_complex/testing_utilities.h b/Tangential_complex/test/Tangential_complex/testing_utilities.h index 810b5063fcd..1c70713f7d8 100644 --- a/Tangential_complex/test/Tangential_complex/testing_utilities.h +++ b/Tangential_complex/test/Tangential_complex/testing_utilities.h @@ -32,8 +32,12 @@ #include #include #include +#include +#include +#include #include +#include // Actually, this is very slow because the "m_points_ds->insert" // cleans the tree, which is thus built at each query_ANN call @@ -206,11 +210,52 @@ sparsify_point_set( return output; } -template -bool load_points_from_file( - const std::string &filename, OutputIterator points, +template< + typename Kernel, typename OutputIteratorPoints> + bool load_points_from_file( + const std::string &filename, + OutputIteratorPoints points, std::size_t only_first_n_points = std::numeric_limits::max()) { + typedef typename Kernel::Point_d Point; + + std::ifstream in(filename); + if (!in.is_open()) + { + std::cerr << "Could not open '" << filename << "'" << std::endl; + return false; + } + + Point p; + int num_ppints; + in >> num_ppints; + + std::size_t i = 0; + while (i < only_first_n_points && in >> p) + { + *points++ = p; + ++i; + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << "'" << filename << "' loaded." << std::endl; +#endif + + return true; + } + +template< + typename Kernel, typename Tangent_space_basis, + typename OutputIteratorPoints, typename OutputIteratorTS> +bool load_points_from_file( + const std::string &filename, + OutputIteratorPoints points, + OutputIteratorTS tangent_spaces, + std::size_t only_first_n_points = std::numeric_limits::max()) +{ + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + std::ifstream in(filename); if (!in.is_open()) { @@ -218,14 +263,29 @@ bool load_points_from_file( return false; } + bool contains_tangent_spaces = + (filename.substr(filename.size() - 3) == "pwt"); + + Kernel k; Point p; - int dim_from_file; - in >> dim_from_file; + int num_ppints; + in >> num_ppints; std::size_t i = 0; while(i < only_first_n_points && in >> p) { *points++ = p; + if (contains_tangent_spaces) + { + Tangent_space_basis tsb(i); + for (int d = 0 ; d < 2 ; ++d) // CJTODO : pas toujours "2" + { + Vector v; + in >> v; + tsb.push_back(CGAL::Tangential_complex_::normalize_vector(v, k)); + } + *tangent_spaces++ = tsb; + } ++i; } From 4016d0d247c4018256552ecfa3016a0c0b6b3afa Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 15:38:44 +0100 Subject: [PATCH 396/487] operator>> for Vector_d --- .../CGAL/IO/Triangulation_off_ostream.h | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index dc795045782..d7c8a6ce38e 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -173,6 +173,32 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) return is; } +// TODO: test if the stream is binary or text? +template +std::istream & +operator>>(std::istream &is, typename Wrap::Vector_d & v) +{ + typedef typename Wrap::Vector_d V; + typedef typename K::FT FT; + std::vector coords; + + std::string line; + for (;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + while (line_sstr >> temp) + coords.push_back(temp); + + v = V(coords.begin(), coords.end()); + return is; +} + template < class GT, class TDS > std::ostream & export_triangulation_to_off(std::ostream & os, From 018ee665578814561f28daedac6a59c7e291908a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 15:54:31 +0100 Subject: [PATCH 397/487] Add alpha TC + point set protection + another test to solve inconsistencies Test: see check_and_solve_inconsistencies_by_filtering_simplices_out() --- .../Tangential_complex/benchmark_tc.cpp | 108 ++- .../include/CGAL/Tangential_complex.h | 712 +++++++++++++----- 2 files changed, 599 insertions(+), 221 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 299d1a0458a..5b8f79e1369 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -6,6 +6,9 @@ # define TBB_USE_THREADING_TOOL #endif + +#include // CJTODO TEST + #include #include #include @@ -36,14 +39,17 @@ const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt"; typedef CGAL::Epick_d Kernel; typedef Kernel::FT FT; typedef Kernel::Point_d Point; +typedef Kernel::Vector_d Vector; typedef CGAL::Tangential_complex< Kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag> TC; +//#define CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +//#define TC_PROTECT_POINT_SET_DELTA 0.003 //#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test //#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY -#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points -#define TC_NO_EXPORT +//#define TC_INPUT_STRIDES 10 // only take one point every TC_INPUT_STRIDES points +//#define TC_NO_EXPORT #ifdef JUST_BENCHMARK_SPATIAL_SEARCH std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); @@ -217,8 +223,10 @@ bool export_to_off( } void make_tc(std::vector &points, + TC::TS_container const& tangent_spaces, // can be empty int intrinsic_dim, - double sparsity = 0., + bool sparsify = true, + double sparsity = 0.01, bool perturb = true, bool add_high_dim_simpl = false, bool collapse = false, @@ -226,6 +234,12 @@ void make_tc(std::vector &points, const char *input_name = "tc") { Kernel k; + + if (sparsify && !tangent_spaces.empty()) + { + std::cerr << "Error: cannot sparsify point set with pre-computed normals.\n"; + return; + } // CJTODO TEMP TEST //TC::Simplicial_complex compl; @@ -275,14 +289,14 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM std::vector points_not_sparse = points; #endif //=========================================================================== // Sparsify point set if requested //=========================================================================== - if (sparsity != 0.) + if (sparsify) { std::size_t num_points_before = points.size(); points = sparsify_point_set(k, points, sparsity*sparsity); @@ -290,6 +304,27 @@ void make_tc(std::vector &points, << num_points_before << " / " << points.size() << std::endl; } +#ifdef TC_PROTECT_POINT_SET_DELTA + // CJTODO TEST +# ifdef CGAL_TC_PROFILING + Wall_clock_timer t_protection; +# endif + + std::vector points2; + std::vector dummy; + std::vector > dummy2; + landmark_choice_protected_delaunay( + points, points.size(), points2, dummy, TC_PROTECT_POINT_SET_DELTA, dummy2, false, true); + points = points2; + +# ifdef CGAL_TC_PROFILING + std::cerr << "Point set protected in " << t_protection.elapsed() + << " seconds." << std::endl; +# endif + + std::cerr << "Number of points after PROTECTION: " << points.size() << "\n"; +#endif + CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); @@ -297,13 +332,18 @@ void make_tc(std::vector &points, // Compute Tangential Complex //=========================================================================== -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM TC tc(points.begin(), points.end(), sparsity, intrinsic_dim, points_not_sparse.begin(), points_not_sparse.end(), k); #else TC tc(points.begin(), points.end(), sparsity, intrinsic_dim, k); #endif + if (!tangent_spaces.empty()) + { + tc.set_tangent_planes(tangent_spaces); + } + double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); @@ -356,7 +396,7 @@ void make_tc(std::vector &points, //=========================================================================== t.reset(); double export_before_time = - (export_to_off(tc, input_name_stripped, "_BEFORE_FIX") ? t.elapsed() : -1); + (export_to_off(tc, input_name_stripped, "_INITIAL_TC") ? t.elapsed() : -1); t.reset(); unsigned int num_perturb_steps = 0; @@ -406,6 +446,9 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", "N/A"); } + // CJTODO TEST + //tc.check_and_solve_inconsistencies_by_filtering_simplices_out(); + int max_dim = -1; double fix2_time = -1; double export_after_fix2_time = -1.; @@ -447,14 +490,14 @@ void make_tc(std::vector &points, complex.display_stats(); - // Export to OFF with higher-dim simplices colored - std::set > higher_dim_simplices; + // CJTODO TEMP: Export to OFF with higher-dim simplices colored + /*std::set > higher_dim_simplices; complex.get_simplices_matching_test( Test_dim(intrinsic_dim + 1), std::inserter(higher_dim_simplices, higher_dim_simplices.begin())); export_to_off( tc, input_name_stripped, "_BEFORE_COLLAPSE", false, &complex, - &higher_dim_simplices); + &higher_dim_simplices);*/ //=========================================================================== // Collapse @@ -484,18 +527,23 @@ void make_tc(std::vector &points, //=========================================================================== // Export to OFF //=========================================================================== - t.reset(); - bool exported = export_to_off( - tc, input_name_stripped, "_AFTER_COLLAPSE", false, &complex, - &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, - &unconnected_stars_simplices); - std::cerr - << " OFF colors:" << std::endl - << " * Red: wrong dim simplices" << std::endl - << " * Green: wrong number of cofaces simplices" << std::endl - << " * Blue: not-connected stars" << std::endl; - double export_after_collapse_time = (exported ? t.elapsed() : -1); - t.reset(); + + double export_after_collapse_time = -1.; + if (collapse) + { + t.reset(); + bool exported = export_to_off( + tc, input_name_stripped, "_AFTER_COLLAPSE", false, &complex, + &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, + &unconnected_stars_simplices); + std::cerr + << " OFF colors:" << std::endl + << " * Red: wrong dim simplices" << std::endl + << " * Green: wrong number of cofaces simplices" << std::endl + << " * Blue: not-connected stars" << std::endl; + double export_after_collapse_time = (exported ? t.elapsed() : -1.); + t.reset(); + } //=========================================================================== // Display info @@ -550,7 +598,7 @@ int main() # ifdef _DEBUG int num_threads = 1; # else - int num_threads = 10; + int num_threads = 8; # endif #endif @@ -608,6 +656,7 @@ int main() std::size_t num_points; int ambient_dim; int intrinsic_dim; + char sparsify; double sparsity; char perturb, add_high_dim_simpl, collapse; double time_limit_for_perturb; @@ -619,6 +668,7 @@ int main() sstr >> num_points; sstr >> ambient_dim; sstr >> intrinsic_dim; + sstr >> sparsify; sstr >> sparsity; sstr >> perturb; sstr >> add_high_dim_simpl; @@ -657,6 +707,7 @@ int main() #endif std::vector points; + TC::TS_container tangent_spaces; if (input == "generate_moment_curve") { @@ -728,8 +779,9 @@ int main() } else { - load_points_from_file( - input, std::back_inserter(points)/*, 600*/); + load_points_from_file( + input, std::back_inserter(points), + std::back_inserter(tangent_spaces)/*, 600*/); } #ifdef CGAL_TC_PROFILING @@ -747,9 +799,9 @@ int main() << " points.\n" << "****************************************\n"; #endif - make_tc(points, intrinsic_dim, sparsity, // strided: CJTODO TEMP - perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', - time_limit_for_perturb, input.c_str()); + make_tc(points, tangent_spaces, intrinsic_dim, sparsify=='Y', + sparsity, perturb=='Y', add_high_dim_simpl=='Y', + collapse=='Y', time_limit_for_perturb, input.c_str()); std::cerr << "TC #" << i++ << " done." << std::endl; std::cerr << std::endl << "---------------------------------" diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6e0a9280507..73df4839054 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -37,6 +37,8 @@ #include #include #include +#include +#include # include @@ -47,6 +49,8 @@ #include #include +#include +#include #include #include @@ -65,6 +69,12 @@ # include #endif +// choose exact integral type for QP solver +// (Gmpzf is not thread-safe) +#include +typedef CGAL::MP_Float ET; +//#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 + //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) //static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP @@ -98,7 +108,7 @@ private: /// The class Tangential_complex represents a tangential complex template < - typename Kernel_, // ambiant dimension + typename Kernel_, // ambiant kernel typename DimensionTag, // intrinsic dimension typename Concurrency_tag = CGAL::Parallel_tag, #ifdef CGAL_ALPHA_TC @@ -149,9 +159,6 @@ class Tangential_complex typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename Tr_traits::Vector_d Tr_vector; - typedef Basis Tangent_space_basis; - typedef Basis Orthogonal_space_basis; - typedef std::vector Points; #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) typedef tbb::mutex Mutex_for_perturb; @@ -212,11 +219,14 @@ class Tangential_complex }; public: - typedef typename std::vector TS_container; - typedef typename std::vector OS_container; + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; + typedef std::vector TS_container; + typedef std::vector OS_container; + private: - typedef typename std::vector Tr_container; - typedef typename std::vector Vectors; + typedef std::vector Tr_container; + typedef std::vector Vectors; // An Incident_simplex is the list of the vertex indices // except the center vertex @@ -262,6 +272,22 @@ private: { return vh->point(); } + struct First_of_pair + { + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type::first_type const& type; + }; + + template + typename Pair::first_type const& operator()(Pair const& pair) const + { + return pair.first; + } + }; public: typedef Tangential_complex_::Simplicial_complex Simplicial_complex; @@ -270,7 +296,7 @@ public: template Tangential_complex(InputIterator first, InputIterator last, double sparsity, int intrinsic_dimension, -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM InputIterator first_for_tse, InputIterator last_for_tse, #endif const K &k = K() @@ -295,7 +321,7 @@ public: #ifdef CGAL_TC_EXPORT_NORMALS , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) #endif -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) #endif @@ -581,9 +607,10 @@ public: << stats_before.second << " (" << 100. * stats_before.second / stats_before.first << "%)" << std::endl - << " * Num inconsistent stars: " + /*<< " * Num inconsistent stars: " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" + << std::endl*/ << std::endl << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " @@ -752,7 +779,46 @@ public: << 100. * stats_after.second / stats_after.first << "%" << std::endl; } - + + // Returns true if some inconsistencies were found + bool check_and_solve_inconsistencies_by_filtering_simplices_out() + { + // CJTODO TEMP + std::pair stats_before = + number_of_inconsistent_simplices(false); + std::cerr << "BEFORE check_and_solve_inconsistencies_by_filtering_simplices_out():\n" + << " - Total number of simplices in stars (incl. duplicates): " + << stats_before.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_before.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_before.second / stats_before.first << "%" + << std::endl; + + bool inconsistencies_found = false; + + // CJTODO: parallel_for??? + for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) + { + if (filter_inconsistent_simplices_in_a_local_triangulation(idx)) + inconsistencies_found = true; + } + + // CJTODO TEMP + std::pair stats_after = + number_of_inconsistent_simplices(false); + std::cerr << "AFTER check_and_solve_inconsistencies_by_filtering_simplices_out():\n" + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_after.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_after.first << "%" + << std::endl; + + return inconsistencies_found; + } + #ifdef CGAL_ALPHA_TC private: @@ -804,21 +870,71 @@ private: // star(p) does not contain "s" std::size_t p = *it_p; - // Compute the intersection between aff(Voronoi_cell(s)) and Tq - boost::optional intersection = - compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + boost::optional intersection; + + // If we know the intersection between Tq and voronoi(s) is a point + // I.e. dim(Tq) + dim(V(full_simplex)) = D + // <=> dim(Tq) = dim(full_simplex) + if (q_tr.current_dimension() == s.size()) + { + // Compute the intersection between aff(Voronoi_cell(s)) and Tq + // Note that the computation in done in the sub-space defined by Tq + intersection = + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + q_tr.current_dimension(), + project_points_and_compute_weights( + full_simplex, m_tangent_spaces[i], q_tr.geom_traits()), + m_tangent_spaces[i], + q_tr.geom_traits()); + + // CJTODO: replace with an assertion? + if (!intersection) + { + std::cerr << "ERROR fill_pqueues_for_alpha_tc: " + "aff(Voronoi_cell(s)) and Tq do not intersect.\n"; + continue; + } + } + else + { + std::cerr << "***************** Intersection is not a point ********************\n"; // CJTODO TEMP + // Compute the intersection between Voronoi_cell(s) and Tq + // We need Q, i.e. the vertices which are common neighbors of all + // vertices of full_simplex in the Delaunay triangulation, but we + // don't have, so we use the 5^d nearest neighbors instead + int num_neighbors_for_Q_approx = std::pow( + BASE_VALUE_FOR_ALPHA_TC_NEIGHBORHOOD, m_intrinsic_dim); + const Point center_pt = compute_perturbed_point(p); + KNS_range ins_range = m_points_ds.query_ANN( + center_pt, num_neighbors_for_Q_approx); + + // CJTODO: optimize that, use a vector! + std::set Q( + boost::make_counting_iterator(std::size_t(0)), + boost::make_counting_iterator(m_points.size())); + for (auto i : full_simplex) + Q.erase(i); + + intersection = + compute_voronoi_face_and_tangent_subspace_intersection( q_tr.current_dimension(), project_points_and_compute_weights( - full_simplex, m_tangent_spaces[i], q_tr.geom_traits()), + full_simplex, m_tangent_spaces[i], q_tr.geom_traits()), + project_points_and_compute_weights( + Q, + //boost::counting_range(std::size_t(0), m_points.size() - 1), + //boost::adaptors::transform(ins_range, First_of_pair()), + m_tangent_spaces[i], q_tr.geom_traits()), m_tangent_spaces[i], q_tr.geom_traits()); - // CJTODO: replace with an assertion? - if (!intersection) - { - std::cerr << "ERROR fill_pqueues_for_alpha_tc: " - "aff(Voronoi_cell(s)) and Tq do not intersect.\n"; - continue; + // CJTODO: replace with an assertion? + if (!intersection) + { + std::cerr << "ERROR fill_pqueues_for_alpha_tc: " + "Voronoi_cell(s) and Tq do not intersect.\n"; + continue; + } } // The following computations are done in the Euclidian space @@ -1436,6 +1552,205 @@ private: return *s.rbegin() == std::numeric_limits::max(); } + // Output: "triangulation" is a Regular Triangulation containing at least the + // star of "center_pt" + // Returns the handle of the center vertex + Tr_vertex_handle compute_star( + std::size_t i, const Point ¢er_pt, const Tangent_space_basis &tsb, + Triangulation &triangulation, bool verbose = false) + { + int tangent_space_dim = tsb.dimension(); + const Tr_traits &local_tr_traits = triangulation.geom_traits(); + Tr_vertex_handle center_vertex; + + // Kernel functor & objects + typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); + + // Triangulation's traits functor & objects + typename Tr_traits::Point_weight_d point_weight = + local_tr_traits.point_weight_d_object(); + typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object(); + + //*************************************************** + // Build a minimal triangulation in the tangent space + // (we only need the star of p) + //*************************************************** + + // Insert p + Tr_point proj_wp; + if (i == tsb.origin()) + { + // Insert {(0, 0, 0...), m_weights[i]} + proj_wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(tangent_space_dim, ORIGIN), + m_weights[i]); + } + else + { + const Weighted_point& wp = compute_perturbed_weighted_point(i); + proj_wp = project_point_and_compute_weight(wp, tsb, local_tr_traits); + } + + center_vertex = triangulation.insert(proj_wp); + center_vertex->data() = i; + if (verbose) + std::cerr << "* Inserted point #" << i << std::endl; + +#ifdef CGAL_TC_VERY_VERBOSE + std::size_t num_attempts_to_insert_points = 1; + std::size_t num_inserted_points = 1; +#endif + //const int NUM_NEIGHBORS = 150; + //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); + INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); + + // While building the local triangulation, we keep the radius + // of the sphere "star sphere" centered at "center_vertex" + // and which contains all the + // circumspheres of the star of "center_vertex" + boost::optional squared_star_sphere_radius_plus_margin; + +#ifdef CGAL_ALPHA_TC + /*FT max_absolute_alpha = tsb.max_absolute_alpha(); + // "2*m_half_sparsity" because both points can be perturbed + FT max_sqdist_to_tangent_space = (max_absolute_alpha == FT(0) ? + FT(0) : CGAL::square(2*max_absolute_alpha + 2*m_half_sparsity));*/ + std::size_t number_of_attempts_to_insert_points = 0; + const std::size_t MAX_NUM_INSERTED_POINTS = + tsb.num_thickening_vectors() > 0 ? + static_cast(std::pow(BASE_VALUE_FOR_ALPHA_TC_NEIGHBORHOOD, /*tsb.dimension()*/m_intrinsic_dim)) + : std::numeric_limits::max(); +#endif + + // Insert points until we find a point which is outside "star shere" + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { +#ifdef CGAL_ALPHA_TC + ++number_of_attempts_to_insert_points; + /*if (number_of_attempts_to_insert_points > MAX_NUM_INSERTED_POINTS) + break;*/ +#endif + + std::size_t neighbor_point_idx = nn_it->first; + + // ith point = p, which is already inserted + if (neighbor_point_idx != i) + { + // No need to lock the Mutex_for_perturb here since this will not be + // called while other threads are perturbing the positions + Point neighbor_pt; + FT neighbor_weight; + compute_perturbed_weighted_point( + neighbor_point_idx, neighbor_pt, neighbor_weight); + + if (squared_star_sphere_radius_plus_margin + && k_sqdist(center_pt, neighbor_pt) + > *squared_star_sphere_radius_plus_margin) + break; + + Tr_point proj_pt = project_point_and_compute_weight( + neighbor_pt, neighbor_weight, tsb, + local_tr_traits); + +#ifdef CGAL_ALPHA_TC + /*for (int i = 0 ; i < tsb.num_thickening_vectors() ; ++i) + { + FT c = coord(proj_pt, m_intrinsic_dim + i); + if (c > 2.5*tsb.alpha_plus(i) + 2*m_half_sparsity //CJTODO: il faut 2*tsb.alpha_plus(i) + || c < 2.5*tsb.alpha_minus(i) - 2*m_half_sparsity) //CJTODO: il faut 2*tsb.alpha_minus(i) + { + goto end_of_insert_loop; // "continue" in n-2 for-loop + } + + }*/ + /*if (max_sqdist_to_tangent_space != FT(0) + && center_to_nbor_sqdist > max_sqdist_to_tangent_space) + break;*/ +#endif + + +#ifdef CGAL_TC_VERY_VERBOSE + ++num_attempts_to_insert_points; +#endif + + + Tr_vertex_handle vh = triangulation.insert_if_in_star(proj_pt, center_vertex); + //Tr_vertex_handle vh = triangulation.insert(proj_pt); + if (vh != Tr_vertex_handle()) + { +#ifdef CGAL_TC_VERY_VERBOSE + ++num_inserted_points; +#endif + if (verbose) + std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; + + vh->data() = neighbor_point_idx; + + // Let's recompute squared_star_sphere_radius_plus_margin + if (triangulation.current_dimension() >= tangent_space_dim) + { + squared_star_sphere_radius_plus_margin = boost::none; + // Get the incident cells and look for the biggest circumsphere + std::vector incident_cells; + triangulation.incident_full_cells( + center_vertex, + std::back_inserter(incident_cells)); + for (typename std::vector::iterator cit = + incident_cells.begin(); cit != incident_cells.end(); ++cit) + { + Tr_full_cell_handle cell = *cit; + if (triangulation.is_infinite(cell)) + { + squared_star_sphere_radius_plus_margin = boost::none; + break; + } + else + { + Tr_point c = power_center( + boost::make_transform_iterator( + cell->vertices_begin(), + vertex_handle_to_point), + boost::make_transform_iterator( + cell->vertices_end(), + vertex_handle_to_point)); + + FT sq_power_sphere_diam = 4 * point_weight(c); + + if (!squared_star_sphere_radius_plus_margin + || sq_power_sphere_diam > + *squared_star_sphere_radius_plus_margin) + { + squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; + } + } + } + + // Let's add the margin, now + // The value depends on whether we perturb weight or position + if (squared_star_sphere_radius_plus_margin) + { +#ifdef CGAL_TC_PERTURB_WEIGHT + // "4*m_sq_half_sparsity" because both points can be perturbed + squared_star_sphere_radius_plus_margin = + *squared_star_sphere_radius_plus_margin + 4 * m_sq_half_sparsity; +#else + // "2*m_half_sparsity" because both points can be perturbed + squared_star_sphere_radius_plus_margin = CGAL::square( + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + + 2 * m_half_sparsity); +#endif + } + } + } + } + } + + return center_vertex; + } + void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) @@ -1484,176 +1799,9 @@ private: int tangent_space_dim = tangent_basis_dim(i); Triangulation &local_tr = m_triangulations[i].construct_triangulation(tangent_space_dim); - const Tr_traits &local_tr_traits = local_tr.geom_traits(); - Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); - // Kernel functor & objects - typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); - - // Triangulation's traits functor & objects - typename Tr_traits::Point_weight_d point_weight = - local_tr_traits.point_weight_d_object(); - typename Tr_traits::Power_center_d power_center = - local_tr_traits.power_center_d_object(); - - - //*************************************************** - // Build a minimal triangulation in the tangent space - // (we only need the star of p) - //*************************************************** - - // Insert p - Tr_point proj_wp; - if(i == tsb.origin()) - { - proj_wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(tangent_space_dim, ORIGIN), - m_weights[i]); - } - else - { - const Weighted_point& wp = compute_perturbed_weighted_point(i); - proj_wp = project_point_and_compute_weight(wp, tsb, local_tr_traits); - } - - center_vertex = local_tr.insert(proj_wp); - center_vertex->data() = i; - if (verbose) - std::cerr << "* Inserted point #" << i << std::endl; - -#ifdef CGAL_TC_VERY_VERBOSE - std::size_t num_attempts_to_insert_points = 1; - std::size_t num_inserted_points = 1; -#endif - //const int NUM_NEIGHBORS = 150; - //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); - INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); - - // While building the local triangulation, we keep the radius - // of the sphere "star sphere" centered at "center_vertex" - // and which contains all the - // circumspheres of the star of "center_vertex" - boost::optional squared_star_sphere_radius_plus_margin; - -#ifdef CGAL_ALPHA_TC - /*FT max_absolute_alpha = tsb.max_absolute_alpha(); - // "2*m_half_sparsity" because both points can be perturbed - FT max_sqdist_to_tangent_space = (max_absolute_alpha == FT(0) ? - FT(0) : CGAL::square(2*max_absolute_alpha + 2*m_half_sparsity));*/ - std::size_t number_of_attempts_to_insert_points = 0; - const std::size_t MAX_NUM_INSERTED_POINTS = - tsb.num_thickening_vectors() > 0 ? - static_cast(std::pow(4, /*tsb.dimension()*/m_intrinsic_dim)) - : std::numeric_limits::max(); -#endif - - // Insert points until we find a point which is outside "star shere" - for (INS_iterator nn_it = ins_range.begin() ; - nn_it != ins_range.end() ; - ++nn_it) - { -#ifdef CGAL_ALPHA_TC - ++number_of_attempts_to_insert_points; - if (number_of_attempts_to_insert_points > MAX_NUM_INSERTED_POINTS) - break; -#endif - - std::size_t neighbor_point_idx = nn_it->first; - - // ith point = p, which is already inserted - if (neighbor_point_idx != i) - { - // No need to lock the Mutex_for_perturb here since this will not be - // called while other threads are perturbing the positions - Point neighbor_pt; - FT neighbor_weight; - compute_perturbed_weighted_point( - neighbor_point_idx, neighbor_pt, neighbor_weight); - - if (squared_star_sphere_radius_plus_margin - && k_sqdist(center_pt, neighbor_pt) - > *squared_star_sphere_radius_plus_margin) - break; - - Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, neighbor_weight, tsb, - local_tr_traits); - -#ifdef CGAL_TC_VERY_VERBOSE - ++num_attempts_to_insert_points; -#endif - - - Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); - //Tr_vertex_handle vh = local_tr.insert(proj_pt); - if (vh != Tr_vertex_handle()) - { -#ifdef CGAL_TC_VERY_VERBOSE - ++num_inserted_points; -#endif - if (verbose) - std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; - - vh->data() = neighbor_point_idx; - - // Let's recompute squared_star_sphere_radius_plus_margin - if (local_tr.current_dimension() >= tangent_space_dim) - { - squared_star_sphere_radius_plus_margin = boost::none; - // Get the incident cells and look for the biggest circumsphere - std::vector incident_cells; - local_tr.incident_full_cells( - center_vertex, - std::back_inserter(incident_cells)); - for (typename std::vector::iterator cit = - incident_cells.begin(); cit != incident_cells.end(); ++cit) - { - Tr_full_cell_handle cell = *cit; - if (local_tr.is_infinite(cell)) - { - squared_star_sphere_radius_plus_margin = boost::none; - break; - } - else - { - Tr_point c = power_center( - boost::make_transform_iterator( - cell->vertices_begin(), - vertex_handle_to_point), - boost::make_transform_iterator( - cell->vertices_end(), - vertex_handle_to_point)); - - FT sq_power_sphere_diam = 4*point_weight(c); - - if (!squared_star_sphere_radius_plus_margin - || sq_power_sphere_diam > - *squared_star_sphere_radius_plus_margin) - { - squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; - } - } - } - - // Let's add the margin, now - // The value depends on whether we perturb weight or position - if (squared_star_sphere_radius_plus_margin) - { -#ifdef CGAL_TC_PERTURB_WEIGHT - // "4*m_sq_half_sparsity" because both points can be perturbed - squared_star_sphere_radius_plus_margin = - *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; -#else - // "2*m_half_sparsity" because both points can be perturbed - squared_star_sphere_radius_plus_margin = CGAL::square( - CGAL::sqrt(*squared_star_sphere_radius_plus_margin) - + 2*m_half_sparsity); -#endif - } - } - } - } - } + m_triangulations[i].center_vertex() = + compute_star(i, center_pt, tsb, local_tr, verbose); #if defined(CGAL_TC_PROFILING) && defined(CGAL_TC_VERY_VERBOSE) std::cerr << " - triangulation construction: " << t.elapsed() << " s.\n"; @@ -2003,7 +2151,7 @@ next_face: //typename K::Translated_point_d transl = // m_k.translated_point_d_object(); -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM KNS_range kns_range = m_points_ds_for_tse.query_ANN( p, num_points_for_pca, false); const Points &points_for_pca = m_points_for_tse; @@ -2127,6 +2275,95 @@ next_face: */ } + // Compute the space tangent to a simplex (p1, p2, ... pn) + // CJTODO: Improve this? + // Basically, it takes all the neighbor points to p1, p2... pn and runs PCA + // on it. Note that most points are duplicated. + Tangent_space_basis compute_tangent_space( + const Indexed_simplex &s, bool normalize_basis = true) + { + unsigned int num_points_for_pca = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); + + // Kernel functors + typename K::Construct_vector_d constr_vec = + m_k.construct_vector_d_object(); + typename K::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename K::Squared_length_d sqlen = + m_k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = + m_k.scaled_vector_d_object(); + typename K::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename K::Difference_of_vectors_d diff_vec = + m_k.difference_of_vectors_d_object(); + //typename K::Translated_point_d transl = + // m_k.translated_point_d_object(); + + // One row = one point + Eigen::MatrixXd mat_points(s.size()*num_points_for_pca, m_ambient_dim); + unsigned int current_row = 0; + + for (Indexed_simplex::const_iterator it_index = s.begin(); + it_index != s.end() ; ++it_index) + { + const Point &p = m_points[*it_index]; + +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + KNS_range kns_range = m_points_ds_for_tse.query_ANN( + p, num_points_for_pca, false); + const Points &points_for_pca = m_points_for_tse; +#else + KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); + const Points &points_for_pca = m_points; +#endif + + KNS_iterator nn_it = kns_range.begin(); + for ( ; + current_row < num_points_for_pca && nn_it != kns_range.end() ; + ++current_row, ++nn_it) + { + for (int i = 0 ; i < m_ambient_dim ; ++i) + { + //const Point p = transl( + // points_for_pca[nn_it->first], m_translations[nn_it->first]); + mat_points(current_row, i) = + CGAL::to_double(coord(points_for_pca[nn_it->first], i)); + } + } + } + Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver eig(cov); + + Tangent_space_basis tsb; + + // The eigenvectors are sorted in increasing order of their corresponding + // eigenvalues + for (int j = m_ambient_dim - 1 ; + j >= m_ambient_dim - m_intrinsic_dim ; + --j) + { + if (normalize_basis) + { + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); + tsb.push_back(normalize_vector(v, m_k)); + } + else + { + tsb.push_back(constr_vec( + m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); + } + } + + return tsb; + } + // Returns the dimension of the ith local triangulation // This is particularly useful for the alpha-TC int tangent_basis_dim(std::size_t i) const @@ -2830,6 +3067,95 @@ next_face: return is_inconsistent; } + + bool filter_inconsistent_simplices_in_a_local_triangulation( + std::size_t tr_index) + { + bool is_inconsistent = false; + + Star &star = m_stars[tr_index]; + Triangulation const& tr = m_triangulations[tr_index].tr(); + Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); + const Tr_traits &local_tr_traits = tr.geom_traits(); + int cur_dim = tr.current_dimension(); + + // For each incident simplex + Star::iterator it_inc_simplex = star.begin(); + while (it_inc_simplex != star.end()) + { + const Incident_simplex &incident_simplex = *it_inc_simplex; + + // Don't check infinite cells + if (is_infinite(incident_simplex)) + { + ++it_inc_simplex; + continue; + } + + Indexed_simplex c = incident_simplex; + c.insert(tr_index); // Add the missing index + + // Inconsistent? + if (!is_simplex_consistent(c)) + { + is_inconsistent = true; + + // Compute T, the space tangent to "c" + Tangent_space_basis tsb = compute_tangent_space(c); + + std::size_t center_index = *(c.begin()); + // Compute the star of "center_index" in the RT restricted to T + tsb.set_origin(center_index); + Triangulation tr(m_intrinsic_dim); + Tr_vertex_handle center_vh = compute_star( + center_index, compute_perturbed_point(center_index), tsb, tr); + + // Get incident cells + std::vector incident_cells; + tr.incident_full_cells( + center_vh, std::back_inserter(incident_cells)); + + // Check if "c" is among them + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end = incident_cells.end(); + bool found = false; + // For each cell + for (; !found && it_c != it_c_end ; ++it_c) + { + Incident_simplex incident_simplex; + for (int j = 0 ; j < tr.current_dimension() + 1 ; ++j) + { + std::size_t index = (*it_c)->vertex(j)->data(); + incident_simplex.insert(index); + } + if (incident_simplex == c) + found = true; + } + // If the simplex is not in the new star, we remove it + if (!found) + { + if (it_inc_simplex != star.end() - 1) + { + *it_inc_simplex = star.back(); + star.pop_back(); + } + else + { + star.pop_back(); + it_inc_simplex = star.end(); // end the loop + } + } + else + ++it_inc_simplex; + } + // Consistent + else + ++it_inc_simplex; + } + + return is_inconsistent; + } + std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices, bool use_perturbed_points = false) const @@ -4105,7 +4431,7 @@ private: //std::vector m_tr_mutexes; #endif -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Points m_points_for_tse; Points_ds m_points_ds_for_tse; #endif From 1ede44996cff9130435ae6aee7077a5c8b8102cf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 17:16:56 +0100 Subject: [PATCH 398/487] Add Simplicial_complex::num_K_simplices() --- .../include/CGAL/Tangential_complex.h | 12 +++--- .../Tangential_complex/Simplicial_complex.h | 37 ++++++++++++++++--- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 73df4839054..19c8af98a5d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1355,7 +1355,7 @@ public: std::set * incorrect_simplices = NULL) const { typedef Simplicial_complex::Simplex Simplex; - typedef Simplicial_complex::Simplex_range Simplex_range; + typedef Simplicial_complex::Simplex_set Simplex_set; if (m_points.empty()) return true; @@ -1413,10 +1413,10 @@ public: // save its simplices into "stars_simplices" //------------------------------------------------------------------------- - Simplex_range const *p_simplices; + Simplex_set const *p_simplices; std::size_t num_infinite_cells = 0; - Simplex_range stars_simplices; + Simplex_set stars_simplices; if (!p_complex) { Stars_container::const_iterator it_star = m_stars.begin(); @@ -4186,16 +4186,16 @@ public: const { typedef Simplicial_complex::Simplex Simplex; - typedef Simplicial_complex::Simplex_range Simplex_range; + typedef Simplicial_complex::Simplex_set Simplex_set; // If m_intrinsic_dim = 1, each point is output two times // (see export_vertices_to_off) num_OFF_simplices = 0; std::size_t num_maximal_simplices = 0; - typename Simplex_range::const_iterator it_s = + typename Simplex_set::const_iterator it_s = complex.simplex_range().begin(); - typename Simplex_range::const_iterator it_s_end = + typename Simplex_set::const_iterator it_s_end = complex.simplex_range().end(); // For each simplex for ( ; it_s != it_s_end ; ++it_s) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 199691c0a64..c7a9b58c242 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -43,7 +43,7 @@ class Simplicial_complex { public: typedef std::set Simplex; - typedef std::set Simplex_range; + typedef std::set Simplex_set; void add_simplex( const std::set &s, bool perform_checks = true) @@ -86,7 +86,7 @@ public: m_complex.insert(s); } - const Simplex_range &simplex_range() const + const Simplex_set &simplex_range() const { return m_complex; } @@ -322,6 +322,31 @@ public: return ret; } + template + std::size_t num_K_simplices() + { + std::set k_simplices; + + for (Complex::const_iterator it_simplex = m_complex.begin(), + it_simplex_end = m_complex.end() ; + it_simplex != it_simplex_end ; + ++it_simplex) + { + if (it_simplex->size() == K + 1) + { + k_simplices.insert(*it_simplex); + } + else if (it_simplex->size() > K + 1) + { + // Get the k-faces composing the simplex + combinations( + *it_simplex, K + 1, std::inserter(k_simplices, k_simplices.begin())); + } + } + + return k_simplices.size(); + } + // CJTODO: ADD COMMENTS bool is_pure_pseudomanifold( int simplex_dim, @@ -331,9 +356,9 @@ public: std::size_t *p_num_wrong_dim_simplices = NULL, std::size_t *p_num_wrong_number_of_cofaces = NULL, std::size_t *p_num_unconnected_stars = NULL, - Simplex_range *p_wrong_dim_simplices = NULL, - Simplex_range *p_wrong_number_of_cofaces_simplices = NULL, - Simplex_range *p_unconnected_stars_simplices = NULL) const + Simplex_set *p_wrong_dim_simplices = NULL, + Simplex_set *p_wrong_number_of_cofaces_simplices = NULL, + Simplex_set *p_unconnected_stars_simplices = NULL) const { // If simplex_dim == 1, we do not need to check if stars are connected if (simplex_dim == 1) @@ -512,7 +537,7 @@ public: } private: - typedef Simplex_range Complex; + typedef Simplex_set Complex; // graph is an adjacency list typedef boost::adjacency_list Adj_graph; From 73435c098714994282b1f319e76feb1214a818f7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 Jan 2016 12:50:01 +0100 Subject: [PATCH 399/487] Forgot to commit Mesh_d.h + missing const --- .../Tangential_complex/benchmark_mesh_d.cpp | 16 +- Tangential_complex/include/CGAL/Mesh_d.h | 1181 +++++++++++++++++ .../Tangential_complex/Simplicial_complex.h | 2 +- 3 files changed, 1197 insertions(+), 2 deletions(-) create mode 100644 Tangential_complex/include/CGAL/Mesh_d.h diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp index 8ff7c0d0d67..0e5aea227d1 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -14,6 +14,7 @@ #include #include "../../test/Tangential_complex/testing_utilities.h" +#include "console_color.h" #include #include @@ -168,6 +169,18 @@ void make_mesh( // Stats about the simplices mesh.complex().display_stats(); + std::size_t num_edges = mesh.complex().num_K_simplices<1>(); + std::size_t num_triangles = mesh.complex().num_K_simplices<2>(); + std::cerr << "Euler caract.: V - E + F = " + << mesh.number_of_vertices() + << " - " << (std::ptrdiff_t) num_edges + << " + " << (std::ptrdiff_t) num_triangles + << " = " + << yellow + << (std::ptrdiff_t) mesh.number_of_vertices() + - (std::ptrdiff_t) num_edges + + (std::ptrdiff_t) num_triangles + << white << "\n"; //=========================================================================== // Display info @@ -176,7 +189,8 @@ void make_mesh( std::cerr << std::endl << "================================================" << std::endl << "Number of vertices: " << mesh.number_of_vertices() << std::endl - //<< "Pure pseudomanifold: " << (is_pure_pseudomanifold ? "YES" : "NO") << std::endl + << "Pure pseudomanifold: " << yellow + << (is_pure_pseudomanifold ? "YES" : "NO") << white << std::endl << "Computation times (seconds): " << std::endl << " * Mesh: " << init_time + computation_time << std::endl << " - Init + kd-tree = " << init_time << std::endl diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h new file mode 100644 index 00000000000..7907d2adff9 --- /dev/null +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -0,0 +1,1181 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin + + +#ifndef MESH_D_H +#define MESH_D_H + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +# include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif + +// choose exact integral type for QP solver +// (Gmpzf is not thread-safe) +#include +typedef CGAL::MP_Float ET; +//#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 + +namespace CGAL { + +using namespace Tangential_complex_; + +class Vertex_data +{ +public: + Vertex_data(std::size_t data = std::numeric_limits::max()) + : m_data(data) + {} + operator std::size_t() { return m_data; } + operator std::size_t() const { return m_data; } + +private: + std::size_t m_data; +}; + +/// The class Mesh_d represents a d-dimensional mesh +template < + typename Kernel_, // ambiant kernel + typename DimensionTag, // intrinsic dimension + typename Concurrency_tag = CGAL::Parallel_tag, + typename Tr = Delaunay_triangulation + < + Kernel_, + Triangulation_data_structure + < + typename Kernel_::Dimension, + Triangulation_vertex, + Triangulation_full_cell + > + > +> +class Mesh_d +{ + typedef Kernel_ K; + typedef typename K::FT FT; + typedef typename K::Point_d Point; + typedef typename K::Vector_d Vector; + + typedef Tr Triangulation; + typedef typename Triangulation::Vertex_handle Tr_vertex_handle; + typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; + typedef typename Triangulation::Finite_full_cell_const_iterator + Tr_finite_full_cell_const_iterator; + + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; + + typedef std::vector Points; + + typedef Point_cloud_data_structure Points_ds; + typedef typename Points_ds::KNS_range KNS_range; + typedef typename Points_ds::KNS_iterator KNS_iterator; + typedef typename Points_ds::INS_range INS_range; + typedef typename Points_ds::INS_iterator INS_iterator; + + typedef std::set Vertex_set; + typedef std::set Indexed_simplex; + +public: + typedef std::vector TS_container; + typedef std::vector OS_container; +private: + + // For transform_iterator + static const Point &vertex_handle_to_point(Tr_vertex_handle vh) + { + return vh->point(); + } + // For transform_iterator + static std::size_t vertex_handle_to_index(Tr_vertex_handle vh) + { + return vh->data(); + } + + struct First_of_pair + { + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type::first_type const& type; + }; + + template + typename Pair::first_type const& operator()(Pair const& pair) const + { + return pair.first; + } + }; + +public: + typedef Tangential_complex_::Simplicial_complex Simplicial_complex; + + /// Constructor for a range of points + template + Mesh_d(InputIterator first, InputIterator last, + double sparsity, int intrinsic_dimension, +#ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + InputIterator first_for_tse, InputIterator last_for_tse, +#endif + const K &k = K() + ) + : m_k(k) + , m_intrinsic_dim(intrinsic_dimension) + , m_half_sparsity(0.5*sparsity) + , m_sq_half_sparsity(m_half_sparsity*m_half_sparsity) + , m_ambient_dim(k.point_dimension_d_object()(*first)) + , m_points(first, last) + , m_points_ds(m_points) + , m_are_tangent_spaces_computed(m_points.size(), false) + , m_tangent_spaces(m_points.size(), Tangent_space_basis()) + , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) +#ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + , m_points_for_tse(first_for_tse, last_for_tse) + , m_points_ds_for_tse(m_points_for_tse) +#endif + { + if (sparsity <= 0.) + std::cerr << "!Warning! Sparsity should be > 0\n"; + } + + /// Destructor + ~Mesh_d() + { + } + + int intrinsic_dimension() const + { + return m_intrinsic_dim; + } + int ambient_dimension() const + { + return m_ambient_dim; + } + + std::size_t number_of_vertices() const + { + return m_points.size(); + } + + Simplicial_complex const& complex() + { + return m_complex; + } + + void set_tangent_planes( + const TS_container& tangent_spaces, const OS_container& orthogonal_spaces) + { + CGAL_assertion(m_points.size() == tangent_spaces.size() + && m_points.size() == orthogonal_spaces.size()); + m_tangent_spaces = tangent_spaces; + m_orth_spaces = orthogonal_spaces; + for(std::size_t i=0; i *p_uncertain_simplices = NULL) + { +#if defined(CGAL_MESH_D_PROFILING) && defined(CGAL_LINKED_WITH_TBB) + Wall_clock_timer t; +#endif + + // Tangent and orthogonal spaces + for (std::size_t i = 0; i < m_points.size(); ++i) + { + if (!m_are_tangent_spaces_computed[i]) + { + m_tangent_spaces[i] = compute_tangent_space( + m_points[i], i, true/*normalize*/, &m_orth_spaces[i]); + } + } +#if defined(CGAL_MESH_D_PROFILING) && defined(CGAL_LINKED_WITH_TBB) + std::cerr << "Tangent & orthogonal spaces computed in " << t.elapsed() + << " seconds." << std::endl; + t.reset(); +#endif + + // Ambiant DT + Tr tr(m_ambient_dim); + for (std::size_t i = 0; i < m_points.size(); ++i) + { + Tr_vertex_handle vh = tr.insert(m_points[i]); + vh->data() = i; + } +#if defined(CGAL_MESH_D_PROFILING) && defined(CGAL_LINKED_WITH_TBB) + std::cerr << "Ambient DT computed in " << t.elapsed() + << " seconds." << std::endl; + t.reset(); +#endif + + // Extract complex + // CJTODO: avoid duplicates + parallelize + /*m_complex.clear(); + for (Tr_finite_full_cell_const_iterator cit = tr.finite_full_cells_begin() ; + cit != tr.finite_full_cells_end() ; ++cit) + { + // Enumerate k-dim simplices + CGAL::Combination_enumerator combi( + m_intrinsic_dim + 1, 0, m_ambient_dim + 1); + + for (; !combi.finished() ; ++combi) + { + Indexed_simplex simplex; + std::vector vertices; + for (int i = 0 ; i < m_intrinsic_dim + 1 ; ++i) + { + vertices.push_back(cit->vertex(combi[i])); + simplex.insert(cit->vertex(combi[i])->data()); + } + + Vertex_set Q_set = + get_common_neighbor_vertices(tr, vertices); + // Convert it to a vector, because otherwise, the result of + // boost::adaptors::transform does not provide size() + std::vector Q(Q_set.begin(), Q_set.end()); + bool intersect = does_voronoi_face_and_tangent_subspace_intersect( + boost::adaptors::transform(vertices, vertex_handle_to_point), + boost::adaptors::transform(Q, vertex_handle_to_point), + m_orth_spaces[*simplex.begin()]); // CJTODO: remplacer simplex[0] par un truc plus intelligent + if (intersect) + m_complex.add_simplex(simplex, false); + } + }*/ + + Get_functor::type sum_vecs(m_k); + + // Extract complex + // CJTODO: parallelize + m_complex.clear(); + typedef std::map K_faces_and_neighbor_vertices; + K_faces_and_neighbor_vertices k_faces_and_neighbor_vertices = + get_k_faces_and_neighbor_vertices(tr); + m_complex.clear(); + for (K_faces_and_neighbor_vertices::const_iterator k_face_and_nghb_it = + k_faces_and_neighbor_vertices.begin() ; + k_face_and_nghb_it != k_faces_and_neighbor_vertices.end() ; + ++k_face_and_nghb_it) + { + Vertex_set const& k_face = k_face_and_nghb_it->first; + Vertex_set const& neighbor_vertices = k_face_and_nghb_it->second; + // Convert it to a vector, because otherwise, the result of + // boost::adaptors::transform does not provide size() + std::vector kf(k_face.begin(), k_face.end()); + std::vector nghb( + neighbor_vertices.begin(), neighbor_vertices.end()); + + bool keep_it = false; + bool is_uncertain = false; +#ifdef MESH_D_FILTER_BY_TESTING_ALL_VERTICES_TANGENT_PLANES + int num_intersections = 0; + for (auto vh : kf) // CJTODO C++11 + { + bool intersect = does_voronoi_face_and_tangent_subspace_intersect( + boost::adaptors::transform(kf, vertex_handle_to_point), + boost::adaptors::transform(nghb, vertex_handle_to_point), + m_orth_spaces[vh->data()]); + if (intersect) + ++num_intersections; + } + + if (num_intersections >= 1) + { + keep_it = true; + if (num_intersections < m_intrinsic_dim + 1) + is_uncertain = true; + } +#else + // Compute the intersection with all tangent planes of the vertices + // of the k-face + FT sum_weights = 0; + Vector weighted_sum_of_inters = + m_k.construct_vector_d_object()(m_ambient_dim); + for (auto vh : kf) // CJTODO C++11 + { + boost::optional intersection = + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + boost::adaptors::transform(kf, vertex_handle_to_point), + m_orth_spaces[vh->data()]); + + if (intersection) + { + FT weight = + FT(1) / m_k.squared_distance_d_object()(vh->point(), *intersection); + sum_weights += weight; + weighted_sum_of_inters = sum_vecs( + weighted_sum_of_inters, + m_k.scaled_vector_d_object()( + m_k.point_to_vector_d_object()(*intersection), weight)); + } + else + + } + if (sum_weights > 0) + { + // Compute the weighted barycenter + Point avg_inters = m_k.vector_to_point_d_object()( + m_k.scaled_vector_d_object()( + weighted_sum_of_inters, FT(1) / sum_weights)); + + keep_it = true; + // Check if the averaged intersection "i" is inside the Voronoi cell, i.e. + // for each common neighbor qi, (i - p0) <= (i - qi) + Point const& p0 = (*k_face.begin())->point(); + for (auto neighbor_vh : nghb) // CJTODO: C++11 + { + if (m_k.squared_distance_d_object()(p0, avg_inters) > + m_k.squared_distance_d_object()(neighbor_vh->point(), avg_inters)) + { + keep_it = false; + break; + } + } + } +#endif + + if (keep_it) + { + Indexed_simplex s( + boost::make_transform_iterator(kf.begin(), vertex_handle_to_index), + boost::make_transform_iterator(kf.end(), vertex_handle_to_index)); + m_complex.add_simplex(s, false); + + if (is_uncertain && p_uncertain_simplices) + p_uncertain_simplices->push_back(s); + } + } + +#if defined(CGAL_MESH_D_PROFILING) && defined(CGAL_LINKED_WITH_TBB) + std::cerr << "Mesh extracted in computed in " << t.elapsed() + << " seconds." << std::endl; + t.reset(); +#endif + } + + void display_stats() + { + m_complex.display_stats(); + } + +private: + + class Compare_distance_to_ref_point + { + public: + Compare_distance_to_ref_point(Point const& ref, K const& k) + : m_ref(ref), m_k(k) {} + + bool operator()(Point const& p1, Point const& p2) + { + typename K::Squared_distance_d sqdist = + m_k.squared_distance_d_object(); + return sqdist(p1, m_ref) < sqdist(p2, m_ref); + } + + private: + Point const& m_ref; + K const& m_k; + }; + + bool is_infinite(Indexed_simplex const& s) const + { + return *s.rbegin() == std::numeric_limits::max(); + } + + Tangent_space_basis compute_tangent_space( + const Point &p + , const std::size_t i + , bool normalize_basis = true + , Orthogonal_space_basis *p_orth_space_basis = NULL) + { +#ifdef CGAL_MESH_D_COMPUTE_TANGENT_PLANES_FOR_SPHERE_2 + + double tt[2] = {p[1], -p[0]}; + Vector t(2, &tt[0], &tt[2]); + + // Normalize t1 and t2 + typename K::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + + Tangent_space_basis ts(i); + ts.reserve(m_intrinsic_dim); + ts.push_back(scaled_vec(t, FT(1)/CGAL::sqrt(sqlen(t)))); + m_are_tangent_spaces_computed[i] = true; + + return ts; + +#elif defined(CGAL_MESH_D_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3) + + double tt1[3] = {-p[1] - p[2], p[0], p[0]}; + double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], + p[2] * tt1[0] - p[0] * tt1[2], + p[0] * tt1[1] - p[1] * tt1[0]}; + Vector t1(3, &tt1[0], &tt1[3]); + Vector t2(3, &tt2[0], &tt2[3]); + + // Normalize t1 and t2 + typename K::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + + Tangent_space_basis ts(i); + ts.reserve(m_intrinsic_dim); + ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); + ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); + + m_are_tangent_spaces_computed[i] = true; + + return ts; + +#elif defined(CGAL_MESH_D_COMPUTE_TANGENT_PLANES_FOR_TORUS_D) + + Tangent_space_basis ts(i); + ts.reserve(m_intrinsic_dim); + for (int dim = 0 ; dim < m_intrinsic_dim ; ++dim) + { + std::vector tt(m_ambient_dim, 0.); + tt[2*dim] = -p[2*dim + 1]; + tt[2*dim + 1] = p[2*dim]; + Vector t(2*m_intrinsic_dim, tt.begin(), tt.end()); + ts.push_back(t); + } + + m_are_tangent_spaces_computed[i] = true; + + //return compute_gram_schmidt_basis(ts, m_k); + return ts; + //******************************* PCA ************************************* + +#else + + unsigned int num_points_for_pca = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); + + // Kernel functors + typename K::Construct_vector_d constr_vec = + m_k.construct_vector_d_object(); + typename K::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename K::Squared_length_d sqlen = + m_k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = + m_k.scaled_vector_d_object(); + typename K::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename K::Difference_of_vectors_d diff_vec = + m_k.difference_of_vectors_d_object(); + //typename K::Translated_point_d transl = + // m_k.translated_point_d_object(); + +#ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + KNS_range kns_range = m_points_ds_for_tse.query_ANN( + p, num_points_for_pca, false); + const Points &points_for_pca = m_points_for_tse; +#else + KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); + const Points &points_for_pca = m_points; +#endif + + // One row = one point + Eigen::MatrixXd mat_points(num_points_for_pca, m_ambient_dim); + KNS_iterator nn_it = kns_range.begin(); + for (unsigned int j = 0 ; + j < num_points_for_pca && nn_it != kns_range.end() ; + ++j, ++nn_it) + { + for (int i = 0 ; i < m_ambient_dim ; ++i) + { + //const Point p = transl( + // points_for_pca[nn_it->first], m_translations[nn_it->first]); + mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i)); +#ifdef CGAL_MESH_D_ADD_NOISE_TO_TANGENT_SPACE + mat_points(j, i) += m_random_generator.get_double( + -0.5*m_half_sparsity, 0.5*m_half_sparsity); +#endif + } + } + Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver eig(cov); + + Tangent_space_basis tsb(i); // p = compute_perturbed_point(i) here + + // The eigenvectors are sorted in increasing order of their corresponding + // eigenvalues + for (int j = m_ambient_dim - 1 ; + j >= m_ambient_dim - m_intrinsic_dim ; + --j) + { + if (normalize_basis) + { + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); + tsb.push_back(normalize_vector(v, m_k)); + } + else + { + tsb.push_back(constr_vec( + m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); + } + } + + if (p_orth_space_basis) + { + p_orth_space_basis->set_origin(i); + for (int j = m_ambient_dim - m_intrinsic_dim - 1 ; + j >= 0 ; + --j) + { + if (normalize_basis) + { + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); + p_orth_space_basis->push_back(normalize_vector(v, m_k)); + } + else + { + p_orth_space_basis->push_back(constr_vec( + m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); + } + } + } + + m_are_tangent_spaces_computed[i] = true; + + //************************************************************************* + + //Vector n = m_k.point_to_vector_d_object()(p); + //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); + //std::cerr << "IP = " << scalar_pdct(n, ts[0]) << " & " << scalar_pdct(n, ts[1]) << std::endl; + + return tsb; + +#endif + + /* + // Alternative code (to be used later) + //Vector n = m_k.point_to_vector_d_object()(p); + //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); + //Vector t1(12., 15., 65.); + //Vector t2(32., 5., 85.); + //Tangent_space_basis ts; + //ts.reserve(m_intrinsic_dim); + //ts.push_back(diff_vec(t1, scaled_vec(n, scalar_pdct(t1, n)))); + //ts.push_back(diff_vec(t2, scaled_vec(n, scalar_pdct(t2, n)))); + //ts = compute_gram_schmidt_basis(ts, m_k); + //return ts; + */ + } + + Vertex_set get_neighbor_vertices( + Triangulation const& tr, Tr_vertex_handle vh, + bool keep_infinite_vertex = false) + { + Vertex_set neighbors; + std::vector incident_cells; + tr.incident_full_cells( + vh, std::back_inserter(incident_cells)); + + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end = incident_cells.end(); + // For each cell + for (; it_c != it_c_end ; ++it_c) + { + for (int j = 0 ; j < m_ambient_dim + 1 ; ++j) + { + Tr_vertex_handle v = (*it_c)->vertex(j); + if (keep_infinite_vertex + || v->data() != std::numeric_limits::max()) + { + neighbors.insert(v); + } + } + } + neighbors.erase(vh); + return neighbors; + } + + template + Vertex_set get_common_neighbor_vertices( + Triangulation const& tr, Vertex_range const& vertices) + { + Vertex_range::const_iterator vh_it = vertices.begin(); + Vertex_set common_neighbors = + get_neighbor_vertices(tr, *vh_it); + ++vh_it; + + for (; vh_it != vertices.end() ; ++vh_it) + { + Vertex_set neighbors = get_neighbor_vertices(tr, *vh_it); + Vertex_set former_common_neighbors = common_neighbors; + common_neighbors.clear(); + std::set_intersection( + former_common_neighbors.begin(), former_common_neighbors.end(), + neighbors.begin(), neighbors.end(), + std::inserter(common_neighbors, common_neighbors.begin())); + } + + return common_neighbors; + } + + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + // Note that the computation is made in global coordinates. + template + CGAL::Quadratic_program_solution + compute_voronoi_face_and_tangent_subspace_LP_problem( + Point_range_a const& P, + Point_range_b const& Q, + Orthogonal_space_basis const& orthogonal_subspace_basis) const + { + // Notations: + // Fv: Voronoi k-face + // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) + + typename Kernel::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Point_to_vector_d pt_to_vec = + m_k.point_to_vector_d_object(); + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + + std::size_t card_P = P.size(); + std::size_t card_Q = Q.size(); + + // Linear solver + typedef CGAL::Quadratic_program Linear_program; + typedef CGAL::Quadratic_program_solution LP_solution; + + Linear_program lp(CGAL::SMALLER, false); + int current_row = 0; + + //=========== First set of equations =========== + // For points pi in P + // 2(p0 - pi).x = p0^2 - pi^2 + typename Point_range_a::const_iterator it_p = P.begin(); + Point const& p0 = *it_p; + FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); + ++it_p; + for (typename Point_range_a::const_iterator it_p_end = P.end() ; + it_p != it_p_end ; ++it_p) + { + Point const& pi = *it_p; + + for (int k = 0 ; k < m_ambient_dim ; ++k) + lp.set_a(k, current_row, 2 * (coord(p0, k) - coord(pi, k))); + + FT pi_dot_pi = scalar_pdct(pt_to_vec(pi), pt_to_vec(pi)); + lp.set_b(current_row, p0_dot_p0 - pi_dot_pi); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + //=========== Second set of equations =========== + // For each point qi in Q + // 2(qi - p0).x <= qi^2 - p0^2 + for (typename Point_range_b::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; + it_q != it_q_end ; ++it_q) + { + Point const& qi = *it_q; + + for (int k = 0 ; k < m_ambient_dim ; ++k) + lp.set_a(k, current_row, 2 * (coord(qi, k) - coord(p0, k))); + + FT qi_dot_qi = scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)); + lp.set_b(current_row, qi_dot_qi - p0_dot_p0); + + ++current_row; + } + + //=========== Third set of equations =========== + // For each vector bi of OSB, (x-p).bi = 0 + // <=> bi.x = bi.p + for (Orthogonal_space_basis::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; + it_osb != it_osb_end ; ++it_osb) + { + Vector const& bi = *it_osb; + + for (int k = 0 ; k < m_ambient_dim ; ++k) + { + lp.set_a(k, current_row, coord(bi, k)); + } + + FT bi_dot_p = scalar_pdct(bi, + pt_to_vec(m_points[orthogonal_subspace_basis.origin()])); + lp.set_b(current_row, bi_dot_p); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + //=========== Other LP parameters =========== + lp.set_c(0, 1); // Minimize x[0] + + //=========== Solve ========================= + LP_solution solution = CGAL::solve_linear_program(lp, ET()); + return solution; + } + + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_tangent_subspace_intersect( + Point_range_a const& P, + Point_range_b const& Q, + Orthogonal_space_basis const& orthogonal_subspace_basis) const + { + return compute_voronoi_face_and_tangent_subspace_LP_problem( + P, Q, orthogonal_subspace_basis).status() == CGAL::QP_OPTIMAL; + } + + + // Returns any point of the intersection between a Voronoi cell and a + // tangent space. + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + // Return value: the point coordinates are expressed in global coordinates + template + boost::optional + compute_voronoi_face_and_tangent_subspace_intersection( + Point_range_a const& P, + Point_range_b const& Q, + Orthogonal_space_basis const& orthogonal_subspace_basis) const + { + typedef CGAL::Quadratic_program_solution LP_solution; + + LP_solution sol = compute_voronoi_face_and_tangent_subspace_LP_problem( + P, Q, orthogonal_subspace_basis); + + boost::optional ret; + if (sol.status() == CGAL::QP_OPTIMAL) + { + std::vector p; + p.reserve(m_ambient_dim); + for (LP_solution::Variable_value_iterator + it_v = sol.variable_values_begin(), + it_v_end = sol.variable_values_end() ; + it_v != it_v_end ; ++it_v) + { + p.push_back(to_double(*it_v)); + } + CGAL_assertion(p.size() == m_ambient_dim); + ret = m_k.construct_point_d_object()(m_ambient_dim, p.begin(), p.end()); + } + else + { + ret = boost::none; + } + + return ret; + } + + // Returns any point of the intersection between aff(voronoi_cell) and a + // tangent space. + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Return value: the point coordinates are expressed in the tsb base + template + boost::optional + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + Point_range_a const& P, + Orthogonal_space_basis const& orthogonal_subspace_basis) const + { + // As we're only interested by aff(v), Q is empty + return compute_voronoi_face_and_tangent_subspace_intersection( + P, std::vector(), + orthogonal_subspace_basis); + } + + std::map get_k_faces_and_neighbor_vertices(Triangulation const& tr) + { + typedef std::map K_faces_and_neighbor_vertices; + + // Map that associate a k-face F and the points of its k+1-cofaces + // (except the points of F). Those points are called its "neighbors". + K_faces_and_neighbor_vertices faces_and_neighbors; + + // Fill faces_and_neighbors + typedef K_faces_and_neighbor_vertices::const_iterator FaN_it; + // Parse cells + for (Tr_finite_full_cell_const_iterator cit = tr.finite_full_cells_begin() ; + cit != tr.finite_full_cells_end() ; ++cit) + { + // Add each k-face to faces_and_neighbors + std::vector booleans(m_ambient_dim + 1, true); + std::fill( + booleans.begin(), + booleans.begin() + m_ambient_dim - m_intrinsic_dim, + false); + do + { + Vertex_set k_face; + std::vector remaining_vertices; + for (int i = 0 ; i < m_ambient_dim + 1 ; ++i) + { + if (booleans[i]) + k_face.insert(cit->vertex(i)); + else + remaining_vertices.push_back(cit->vertex(i)); + } + + faces_and_neighbors[k_face].insert( + remaining_vertices.begin(), remaining_vertices.end()); + + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + + return faces_and_neighbors; + } + + // Returns the dimension of the ith local triangulation + // This is particularly useful for the alpha-TC + int tangent_basis_dim(std::size_t i) const + { + return m_tangent_spaces[i].dimension(); + } + +private: + std::ostream &export_vertices_to_off( + std::ostream & os, std::size_t &num_vertices) const + { + if (m_points.empty()) + { + num_vertices = 0; + return os; + } + + // If m_intrinsic_dim = 1, we output each point two times + // to be able to export each segment as a flat triangle with 3 different + // indices (otherwise, Meshlab detects degenerated simplices) + const int N = (m_intrinsic_dim == 1 ? 2 : 1); + + // Kernel functors + typename K::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + + int num_coords = min(m_ambient_dim, 3); +#ifdef CGAL_MESH_D_EXPORT_NORMALS + OS_container::const_iterator it_os = m_orth_spaces.begin(); +#endif + typename Points::const_iterator it_p = m_points.begin(); + typename Points::const_iterator it_p_end = m_points.end(); + // For each point p + for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) + { + Point const& p = *it_p; + for (int ii = 0 ; ii < N ; ++ii) + { + int i = 0; +#if BETTER_EXPORT_FOR_FLAT_TORUS + // For flat torus + os << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 2)) << " " + << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 3)) << " " + << 1 * CGAL::to_double(coord(p, 1)); +#else + for ( ; i < num_coords ; ++i) + os << CGAL::to_double(coord(p, i)) << " "; +#endif + if (i == 2) + os << "0"; + +#ifdef CGAL_MESH_D_EXPORT_NORMALS + for (i = 0 ; i < num_coords ; ++i) + os << " " << CGAL::to_double(coord(*it_os->begin(), i)); +#endif + os << std::endl; + } +#ifdef CGAL_MESH_D_EXPORT_NORMALS + ++it_os; +#endif + } + + num_vertices = N*m_points.size(); + return os; + } + + template + std::ostream &export_simplices_to_off( + std::ostream & os, std::size_t &num_OFF_simplices, + Indexed_simplex_range const *p_simpl_to_color_in_red = NULL, + Indexed_simplex_range const *p_simpl_to_color_in_green = NULL, + Indexed_simplex_range const *p_simpl_to_color_in_blue = NULL) + const + { + typedef Simplicial_complex::Simplex Simplex; + typedef Simplicial_complex::Simplex_set Simplex_set; + + // If m_intrinsic_dim = 1, each point is output two times + // (see export_vertices_to_off) + num_OFF_simplices = 0; + std::size_t num_maximal_simplices = 0; + + typename Simplex_set::const_iterator it_s = + m_complex.simplex_range().begin(); + typename Simplex_set::const_iterator it_s_end = + m_complex.simplex_range().end(); + // For each simplex + for (; it_s != it_s_end ; ++it_s) + { + Simplex c = *it_s; + ++num_maximal_simplices; + + int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue + if (p_simpl_to_color_in_red && + std::find( + p_simpl_to_color_in_red->begin(), + p_simpl_to_color_in_red->end(), + c) != p_simpl_to_color_in_red->end()) + { + color_simplex = 1; + } + else if (p_simpl_to_color_in_green && + std::find( + p_simpl_to_color_in_green->begin(), + p_simpl_to_color_in_green->end(), + c) != p_simpl_to_color_in_green->end()) + { + color_simplex = 2; + } + else if (p_simpl_to_color_in_blue && + std::find( + p_simpl_to_color_in_blue->begin(), + p_simpl_to_color_in_blue->end(), + c) != p_simpl_to_color_in_blue->end()) + { + color_simplex = 3; + } + + // Gather the triangles here + typedef std::vector Triangles; + Triangles triangles; + + std::size_t num_vertices = c.size(); + // Do not export smaller dimension simplices + if (num_vertices < m_intrinsic_dim + 1) + continue; + + // If m_intrinsic_dim = 1, each point is output two times, + // so we need to multiply each index by 2 + // And if only 2 vertices, add a third one (each vertex is duplicated in + // the file when m_intrinsic dim = 2) + if (m_intrinsic_dim == 1) + { + Indexed_simplex tmp_c; + Indexed_simplex::iterator it = c.begin(); + for (; it != c.end() ; ++it) + tmp_c.insert(*it * 2); + if (num_vertices == 2) + tmp_c.insert(*tmp_c.rbegin() + 1); + + c = tmp_c; + } + + if (num_vertices <= 3) + { + triangles.push_back(c); + } + else + { + // num_vertices >= 4: decompose the simplex in triangles + std::vector booleans(num_vertices, false); + std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); + do + { + Indexed_simplex triangle; + Indexed_simplex::iterator it = c.begin(); + for (int i = 0; it != c.end() ; ++i, ++it) + { + if (booleans[i]) + triangle.insert(*it); + } + triangles.push_back(triangle); + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + + // For each cell + Triangles::const_iterator it_tri = triangles.begin(); + Triangles::const_iterator it_tri_end = triangles.end(); + for (; it_tri != it_tri_end ; ++it_tri) + { + // Don't export infinite cells + if (is_infinite(*it_tri)) + continue; + + os << 3 << " "; + Indexed_simplex::const_iterator it_point_idx = it_tri->begin(); + for (; it_point_idx != it_tri->end() ; ++it_point_idx) + { + os << *it_point_idx << " "; + } + + if (p_simpl_to_color_in_red || p_simpl_to_color_in_green + || p_simpl_to_color_in_blue) + { + switch (color_simplex) + { + case 0: os << " 255 255 0"; break; + case 1: os << " 255 0 0"; break; + case 2: os << " 0 255 0"; break; + case 3: os << " 0 0 255"; break; + default: os << " 128 128 128"; break; + } + } + + ++num_OFF_simplices; + os << std::endl; + } + } + +#ifdef CGAL_MESH_D_VERBOSE + std::cerr << std::endl + << "==========================================================" + << std::endl + << "Export from complex to OFF:\n" + << " * Number of vertices: " << m_points.size() << std::endl + << " * Total number of maximal simplices: " << num_maximal_simplices + << std::endl + << "==========================================================" + << std::endl; +#endif + + return os; + } + +public: + template + std::ostream &export_to_off( + std::ostream & os, + Indexed_simplex_range const *p_simpl_to_color_in_red = NULL, + Indexed_simplex_range const *p_simpl_to_color_in_green = NULL, + Indexed_simplex_range const *p_simpl_to_color_in_blue = NULL) const + { + if (m_points.empty()) + return os; + + if (m_ambient_dim < 2) + { + std::cerr << "Error: export_to_off => ambient dimension should be >= 2." + << std::endl; + os << "Error: export_to_off => ambient dimension should be >= 2." + << std::endl; + return os; + } + if (m_ambient_dim > 3) + { + std::cerr << "Warning: export_to_off => ambient dimension should be " + "<= 3. Only the first 3 coordinates will be exported." + << std::endl; + } + + if (m_intrinsic_dim < 1 || m_intrinsic_dim > 3) + { + std::cerr << "Error: export_to_off => intrinsic dimension should be " + "between 1 and 3." + << std::endl; + os << "Error: export_to_off => intrinsic dimension should be " + "between 1 and 3." + << std::endl; + return os; + } + + std::stringstream output; + std::size_t num_simplices, num_vertices; + export_vertices_to_off(output, num_vertices); + export_simplices_to_off( + output, num_simplices, p_simpl_to_color_in_red, + p_simpl_to_color_in_green, p_simpl_to_color_in_blue); + +#ifdef CGAL_MESH_D_EXPORT_NORMALS + os << "N"; +#endif + + os << "OFF \n" + << num_vertices << " " + << num_simplices << " " + << "0 \n" + << output.str(); + + return os; + } + +private: + const K m_k; + const int m_intrinsic_dim; + const double m_half_sparsity; + const double m_sq_half_sparsity; + const int m_ambient_dim; + + Points m_points; + + Points_ds m_points_ds; + std::vector m_are_tangent_spaces_computed; + TS_container m_tangent_spaces; + OS_container m_orth_spaces; + +#ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + Points m_points_for_tse; + Points_ds m_points_ds_for_tse; +#endif + + mutable CGAL::Random m_random_generator; + + Simplicial_complex m_complex; + +}; // /class Tangential_complex + +} // end namespace CGAL + +#endif // MESH_D_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index c7a9b58c242..a0105521ce4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -323,7 +323,7 @@ public: } template - std::size_t num_K_simplices() + std::size_t num_K_simplices() const { std::set k_simplices; From 3160d4ac93ab5c970031d309dd6cfa46a51e4936 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 Jan 2016 12:52:49 +0100 Subject: [PATCH 400/487] Oops --- Tangential_complex/include/CGAL/Mesh_d.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h index 7907d2adff9..94ef8b3a613 100644 --- a/Tangential_complex/include/CGAL/Mesh_d.h +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -352,8 +352,6 @@ public: m_k.scaled_vector_d_object()( m_k.point_to_vector_d_object()(*intersection), weight)); } - else - } if (sum_weights > 0) { From 31ee6ddc181905a25298c5daa136b9cf7fc8c928 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Feb 2016 19:13:24 +0100 Subject: [PATCH 401/487] Faster TC refresh + Improved output + Possibility to specify a custom point projector for exporting + Temporary hack to handle some data with borders + Console colors --- .../Tangential_complex/benchmark_tc.cpp | 61 +++- .../Tangential_complex/console_color.h | 68 ++++ .../include/CGAL/Tangential_complex.h | 303 ++++++++++++++---- .../CGAL/Tangential_complex/Point_cloud.h | 15 + .../CGAL/Tangential_complex/utilities.h | 113 +++++++ 5 files changed, 499 insertions(+), 61 deletions(-) create mode 100644 Tangential_complex/benchmark/Tangential_complex/console_color.h diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 5b8f79e1369..b7dc7484bf5 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -6,9 +6,6 @@ # define TBB_USE_THREADING_TOOL #endif - -#include // CJTODO TEST - #include #include #include @@ -16,6 +13,7 @@ #include #include "../../test/Tangential_complex/testing_utilities.h" +#include "console_color.h" #include #include @@ -48,9 +46,14 @@ typedef CGAL::Tangential_complex< //#define TC_PROTECT_POINT_SET_DELTA 0.003 //#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test //#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY -//#define TC_INPUT_STRIDES 10 // only take one point every TC_INPUT_STRIDES points +//#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points //#define TC_NO_EXPORT + +#ifdef TC_PROTECT_POINT_SET_DELTA +# include // CJTODO TEST +#endif + #ifdef JUST_BENCHMARK_SPATIAL_SEARCH std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); #endif @@ -179,6 +182,19 @@ bool export_to_off( #ifdef TC_NO_EXPORT return true; #endif + +#if 0 + Kernel k; + FT center_pt[] = { -0.5, -CGAL::sqrt(3.) / 2, -0.5, CGAL::sqrt(3.) / 2 }; + FT proj_pt[] = { 0., 0., 0., 0.2 }; + CGAL::Tangential_complex_::S3_to_R3_stereographic_projection + proj_functor(0.2, + Point(4, ¢er_pt[0], ¢er_pt[4]), + k); +#else + CGAL::Identity proj_functor; +#endif + if (tc.intrinsic_dimension() <= 3) { std::stringstream output_filename; @@ -196,7 +212,8 @@ bool export_to_off( *p_complex, off_stream, p_simpl_to_color_in_red, p_simpl_to_color_in_green, - p_simpl_to_color_in_blue); + p_simpl_to_color_in_blue, + proj_functor); #endif } else @@ -214,7 +231,9 @@ bool export_to_off( off_stream, color_inconsistencies, p_simpl_to_color_in_red, p_simpl_to_color_in_green, - p_simpl_to_color_in_blue); + p_simpl_to_color_in_blue, + NULL, + proj_functor); //#endif } return true; @@ -427,6 +446,13 @@ void make_tc(std::vector &points, //tc.check_correlation_between_inconsistencies_and_fatness(); + // CJTODO TEMP + std::cerr << red << "FINAL CHECK:\n" << white; + tc.number_of_inconsistent_simplices(true); + tc.refresh_tangential_complex(); + tc.number_of_inconsistent_simplices(true); + // CJTODO + //========================================================================= // Export to OFF //========================================================================= @@ -466,7 +492,9 @@ void make_tc(std::vector &points, tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); #endif fix2_time = t.elapsed(); t.reset(); + std::cerr << "Exporting the TC as a Simplicial_complex... "; max_dim = tc.export_TC(complex, false); + std::cerr << "done.\n"; /*std::set > not_delaunay_simplices; if (ambient_dim <= 4) { @@ -485,11 +513,29 @@ void make_tc(std::vector &points, } else { + std::cerr << "Exporting the TC as a Simplicial_complex... "; max_dim = tc.export_TC(complex, false); + std::cerr << "done.\n"; } + std::cerr << "Computing stats of the complex...\n"; complex.display_stats(); + if (intrinsic_dim == 2) + { + std::cerr << "Computing Euler characteristic of the complex...\n"; + std::size_t num_vertices = complex.num_K_simplices<0>(); + std::size_t num_edges = complex.num_K_simplices<1>(); + std::size_t num_triangles = complex.num_K_simplices<2>(); + std::cerr << "Euler characteristic: V - E + F = " + << num_vertices << " - " << num_edges << " + " << num_triangles << " = " + << yellow + << (std::ptrdiff_t) num_vertices + - (std::ptrdiff_t) num_edges + + (std::ptrdiff_t) num_triangles + << white << "\n"; + } + // CJTODO TEMP: Export to OFF with higher-dim simplices colored /*std::set > higher_dim_simplices; complex.get_simplices_matching_test( @@ -552,7 +598,8 @@ void make_tc(std::vector &points, std::cerr << std::endl << "================================================" << std::endl << "Number of vertices: " << tc.number_of_vertices() << std::endl - << "Pure pseudomanifold: " << (is_pure_pseudomanifold ? "YES" : "NO") << std::endl + << "Pure pseudomanifold: " << yellow + << (is_pure_pseudomanifold ? "YES" : "NO") << white << std::endl << "Computation times (seconds): " << std::endl << " * Tangential complex: " << init_time + computation_time << std::endl << " - Init + kd-tree = " << init_time << std::endl diff --git a/Tangential_complex/benchmark/Tangential_complex/console_color.h b/Tangential_complex/benchmark/Tangential_complex/console_color.h new file mode 100644 index 00000000000..50554178257 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/console_color.h @@ -0,0 +1,68 @@ +#ifndef CONSOLE_COLOR_H_ +#define CONSOLE_COLOR_H_ + +#include + +#if defined(WIN32) +#include +#endif + +inline std::ostream& blue(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY); +#else + s << "\x1b[0;34m"; +#endif + return s; +} + +inline std::ostream& red(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, FOREGROUND_RED|FOREGROUND_INTENSITY); +#else + s << "\x1b[0;31m"; +#endif + return s; +} + +inline std::ostream& green(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN|FOREGROUND_INTENSITY); +#else + s << "\x1b[0;32m"; +#endif + return s; +} + +inline std::ostream& yellow(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY); +#else + s << "\x1b[0;33m"; +#endif + return s; +} + +inline std::ostream& white(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); +#else + s << "\x1b[0;37m"; +#endif + return s; +} + +#endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 19c8af98a5d..669ce57f4f8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -84,7 +85,8 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE -//#define BETTER_EXPORT_FOR_FLAT_TORUS +//#define CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS +//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 0.96 namespace CGAL { @@ -397,6 +399,7 @@ public: // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); m_stars.resize(m_points.size()); + m_squared_star_spheres_radii_incl_margin.resize(m_points.size(), FT(-1)); #ifdef CGAL_LINKED_WITH_TBB //m_tr_mutexes.resize(m_points.size()); #endif @@ -511,6 +514,40 @@ public: #endif } + // If the list of perturbed points is provided, it is much faster + template + void refresh_tangential_complex( + Point_indices_range const& perturbed_points_indices) + { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif + + // ANN tree containing only the perturbed points + Points_ds updated_pts_ds(m_points, perturbed_points_indices); + +#ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) + { + tbb::parallel_for(tbb::blocked_range(0, m_points.size()), + Refresh_tangent_triangulation(*this, updated_pts_ds) + ); + } + // Sequential + else +#endif // CGAL_LINKED_WITH_TBB + { + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + refresh_tangent_triangulation(i, updated_pts_ds); + } + +#ifdef CGAL_TC_PROFILING + std::cerr << "Tangential complex refreshed in " << t.elapsed() + << " seconds." << std::endl; +#endif + } + // time_limit in seconds: 0 = no fix to do, < 0 = no time limit Fix_inconsistencies_status fix_inconsistencies_using_perturbation( unsigned int &num_steps, @@ -552,6 +589,7 @@ public: while (!done) { std::size_t num_inconsistent_local_tr = 0; + std::vector updated_points; #ifdef CGAL_TC_PROFILING Wall_clock_timer t_fix_step; @@ -562,13 +600,22 @@ public: if (boost::is_convertible::value) { tbb::combinable num_inconsistencies; + tbb::combinable > tls_updated_points; tbb::parallel_for( tbb::blocked_range(0, m_triangulations.size()), Try_to_solve_inconsistencies_in_a_local_triangulation( - *this, num_inconsistencies) + *this, num_inconsistencies, tls_updated_points) ); num_inconsistent_local_tr = num_inconsistencies.combine(std::plus()); + updated_points = tls_updated_points.combine( + [](std::vector const& x, std::vector const& y) { // CJTODO: C++11 + std::vector res; + res.reserve(x.size() + y.size()); + res.insert(res.end(), x.begin(), x.end()); + res.insert(res.end(), y.begin(), y.end()); + return res; + }); } // Sequential else @@ -577,7 +624,8 @@ public: for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) { num_inconsistent_local_tr += - (try_to_solve_inconsistencies_in_a_local_triangulation(i) ? 1 : 0); + try_to_solve_inconsistencies_in_a_local_triangulation( + i, std::back_inserter(updated_points)); } } @@ -587,42 +635,46 @@ public: #endif #ifdef CGAL_TC_GLOBAL_REFRESH - refresh_tangential_complex(); + if (num_inconsistent_local_tr > 0) + refresh_tangential_complex(updated_points); #endif #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES - std::pair stats_after = - number_of_inconsistent_simplices(false); + if (num_inconsistent_local_tr > 0) + { + std::pair stats_after = + number_of_inconsistent_simplices(false); - std::cerr << std::endl - << "==========================================================" - << std::endl - << "Inconsistencies (detailed stats):\n" - << " * Number of vertices: " << m_points.size() << std::endl - << std::endl - << " * BEFORE fix_inconsistencies_using_perturbation:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " - << stats_before.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second - << " (" << 100. * stats_before.second / stats_before.first << "%)" - << std::endl - /*<< " * Num inconsistent stars: " - << num_inconsistent_local_tr - << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" - << std::endl*/ - << std::endl - << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second - << " (" << 100. * stats_after.second / stats_after.first << "%)" - << std::endl - << "==========================================================" - << std::endl; + std::cerr << std::endl + << "==========================================================" + << std::endl + << "Inconsistencies (detailed stats):\n" + << " * Number of vertices: " << m_points.size() << std::endl + << std::endl + << " * BEFORE fix_inconsistencies_using_perturbation:" << std::endl + << " - Total number of simplices in stars (incl. duplicates): " + << stats_before.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_before.second + << " (" << 100. * stats_before.second / stats_before.first << "%)" + << std::endl + /*<< " * Num inconsistent stars: " + << num_inconsistent_local_tr + << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" + << std::endl*/ + << std::endl + << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_after.second + << " (" << 100. * stats_after.second / stats_after.first << "%)" + << std::endl + << "==========================================================" + << std::endl; - stats_before = stats_after; + stats_before = stats_after; + } #else // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES # ifdef CGAL_TC_VERBOSE @@ -680,7 +732,7 @@ public: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - // Don't export infinite cells + // Don't check infinite cells if (is_infinite(*it_inc_simplex)) continue; @@ -1186,25 +1238,29 @@ public: #endif } #endif // CGAL_ALPHA_TC - + + template > std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, std::set const *p_simpl_to_color_in_red = NULL, std::set const *p_simpl_to_color_in_green = NULL, - std::set const *p_simpl_to_color_in_blue = NULL) + std::set const *p_simpl_to_color_in_blue = NULL, + ProjectionFunctor const& point_projection = ProjectionFunctor()) const { return export_to_off( os, false, p_simpl_to_color_in_red, p_simpl_to_color_in_green, - p_simpl_to_color_in_blue, &complex); + p_simpl_to_color_in_blue, &complex, point_projection); } - + + template > std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, std::set const *p_simpl_to_color_in_red = NULL, std::set const *p_simpl_to_color_in_green = NULL, std::set const *p_simpl_to_color_in_blue = NULL, - const Simplicial_complex *p_complex = NULL) const + const Simplicial_complex *p_complex = NULL, + ProjectionFunctor const& point_projection = ProjectionFunctor()) const { if (m_points.empty()) return os; @@ -1237,7 +1293,7 @@ public: std::stringstream output; std::size_t num_simplices, num_vertices; - export_vertices_to_off(output, num_vertices); + export_vertices_to_off(output, num_vertices, false, point_projection); if (p_complex) { export_simplices_to_off( @@ -1545,12 +1601,68 @@ private: m_tc.compute_tangent_triangulation(i); } }; + + // Functor for resfresh_tangential_complex function + class Refresh_tangent_triangulation + { + Tangential_complex & m_tc; + Points_ds const& m_updated_pts_ds; + + public: + // Constructor + Refresh_tangent_triangulation( + Tangential_complex &tc, Points_ds const& updated_pts_ds) + : m_tc(tc), m_updated_pts_ds(updated_pts_ds) + { } + + // Constructor + Refresh_tangent_triangulation(const Refresh_tangent_triangulation &ctt) + : m_tc(ctt.m_tc), m_updated_pts_ds(ctt.m_updated_pts_ds) + { } + + // operator() + void operator()(const tbb::blocked_range& r) const + { + for (size_t i = r.begin() ; i != r.end() ; ++i) + m_tc.refresh_tangent_triangulation(i, m_updated_pts_ds); + } + }; #endif // CGAL_LINKED_WITH_TBB bool is_infinite(Indexed_simplex const& s) const { return *s.rbegin() == std::numeric_limits::max(); } + + bool is_one_of_the_coord_far_from_origin( + Point const& p, FT limit, int only_test_the_first_n_coords = -1) const + { + typename K::Construct_cartesian_const_iterator_d ccci = + m_k.construct_cartesian_const_iterator_d_object(); + int c = 1; + for (auto it = ccci(p) ; it != ccci(p, 0) ; ++it, ++c) // CJTODO: C++11 + { + if (*it > limit || *it < -limit) + return true; + + if (only_test_the_first_n_coords > 0 && c == only_test_the_first_n_coords) + break; + } + return false; + } + + bool is_one_of_the_coord_far_from_origin( + Indexed_simplex const& s, FT limit, int only_test_the_first_n_coords = -1) const + { + for (Indexed_simplex::const_iterator it_index = s.begin(); + it_index != s.end() ; ++it_index) + { + if (is_one_of_the_coord_far_from_origin( + compute_perturbed_point(*it_index), limit, only_test_the_first_n_coords)) + return true; + } + return false; + } // Output: "triangulation" is a Regular Triangulation containing at least the // star of "center_pt" @@ -1623,7 +1735,7 @@ private: : std::numeric_limits::max(); #endif - // Insert points until we find a point which is outside "star shere" + // Insert points until we find a point which is outside "star sphere" for (INS_iterator nn_it = ins_range.begin() ; nn_it != ins_range.end() ; ++nn_it) @@ -1709,6 +1821,8 @@ private: } else { + // Note that this uses the perturbed point since it uses + // the points of the local triangulation Tr_point c = power_center( boost::make_transform_iterator( cell->vertices_begin(), @@ -1742,6 +1856,13 @@ private: CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2 * m_half_sparsity); #endif + // Save it in `m_squared_star_spheres_radii_incl_margin` + m_squared_star_spheres_radii_incl_margin[i] = + *squared_star_sphere_radius_plus_margin; + } + else + { + m_squared_star_spheres_radii_incl_margin[i] = FT(-1); } } } @@ -1751,6 +1872,36 @@ private: return center_vertex; } + void refresh_tangent_triangulation( + std::size_t i, Points_ds const& updated_pts_ds, bool verbose = false) + { + if (verbose) + std::cerr << "** Refreshing tangent tri #" << i << " **" << std::endl; + + if (m_squared_star_spheres_radii_incl_margin[i] == FT(-1)) + return compute_tangent_triangulation(i, verbose); + + Point center_point = compute_perturbed_point(i); + // Among updated point, what is the closer from our center point? + std::size_t closest_pt_index = + updated_pts_ds.query_ANN(center_point, 1, false).begin()->first; + + typename K::Construct_weighted_point_d k_constr_wp = + m_k.construct_weighted_point_d_object(); + typename K::Power_distance_d k_power_dist = m_k.power_distance_d_object(); + + // Construct a weighted point equivalent to the star sphere + Weighted_point star_sphere = k_constr_wp( + compute_perturbed_point(i), + m_squared_star_spheres_radii_incl_margin[i]); + Weighted_point closest_updated_point = + compute_perturbed_weighted_point(closest_pt_index); + + // Is the "closest point" inside our star sphere? + if (k_power_dist(star_sphere, closest_updated_point) <= FT(0)) + compute_tangent_triangulation(i, verbose); + } + void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) @@ -2640,6 +2791,11 @@ next_face: // CJTODO: improve it like the other "is_simplex_consistent" below bool is_simplex_consistent(Indexed_simplex const& simplex) const { +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(simplex, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + return true; +#endif + // Check if the simplex is in the stars of all its vertices Indexed_simplex::const_iterator it_point_idx = simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p @@ -2680,6 +2836,11 @@ next_face: Indexed_simplex full_simplex = s; full_simplex.insert(center_point); +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(full_simplex, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + return true; +#endif + // Check if the simplex is in the stars of all its vertices Incident_simplex::const_iterator it_point_idx = s.begin(); // For each point p of the simplex, we parse the incidents cells of p @@ -2760,18 +2921,25 @@ next_face: { Tangential_complex & m_tc; tbb::combinable &m_num_inconsistencies; + tbb::combinable > &m_updated_points; public: // Constructor Try_to_solve_inconsistencies_in_a_local_triangulation( - Tangential_complex &tc, tbb::combinable &num_inconsistencies) - : m_tc(tc), m_num_inconsistencies(num_inconsistencies) + Tangential_complex &tc, + tbb::combinable &num_inconsistencies, + tbb::combinable > &updated_points) + : m_tc(tc), + m_num_inconsistencies(num_inconsistencies), + m_updated_points(updated_points) {} // Constructor Try_to_solve_inconsistencies_in_a_local_triangulation( const Compute_tangent_triangulation &ctt) - : m_tc(ctt.m_tc), m_num_inconsistencies(ctt.m_num_inc) + : m_tc(ctt.m_tc), + m_num_inconsistencies(ctt.m_num_inconsistencies), + m_updated_points(ctt.m_updated_points) {} // operator() @@ -2780,7 +2948,8 @@ next_face: for( size_t i = r.begin() ; i != r.end() ; ++i) { m_num_inconsistencies.local() += - m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i); + m_tc.try_to_solve_inconsistencies_in_a_local_triangulation( + i, std::back_inserter(m_updated_points.local())); } } }; @@ -2861,8 +3030,11 @@ next_face: #endif // CGAL_TC_PERTURB_POSITION } + // Return true if inconsistencies were found + template bool try_to_solve_inconsistencies_in_a_local_triangulation( - std::size_t tr_index) + std::size_t tr_index, + OutputIt perturbed_pts_indices = CGAL::Emptyset_iterator()) { bool is_inconsistent = false; @@ -2903,6 +3075,7 @@ next_face: it != c.end() ; ++it) { perturb(*it); + *perturbed_pts_indices++ = *it; } # if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -2930,6 +3103,7 @@ next_face: std::size_t idx = (*it_c)->vertex(k)->data();*/ perturb(idx); + *perturbed_pts_indices++ = idx; # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); @@ -2962,6 +3136,7 @@ next_face: it != the_1_star.end() ; ++it) { perturb(*it); + *perturbed_pts_indices++ = *it; } # if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -3026,6 +3201,7 @@ next_face: ++it) { perturb(*it); + *perturbed_pts_indices++ = *it; } # if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -3045,12 +3221,16 @@ next_face: is_inconsistent = true; int rnd = m_random_generator.get_int(0, static_cast(c.size())); if (rnd == 0) + { perturb(tr_index); + *perturbed_pts_indices++ = tr_index; + } else { Indexed_simplex::const_iterator it_idx = c.begin(); std::advance(it_idx, rnd - 1); perturb(*it_idx); + *perturbed_pts_indices++ = *it_idx; } # if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -3156,9 +3336,11 @@ next_face: return is_inconsistent; } + template > std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices, - bool use_perturbed_points = false) const + bool use_perturbed_points = false, + ProjectionFunctor const& point_projection = ProjectionFunctor()) const { if (m_points.empty()) { @@ -3184,11 +3366,12 @@ next_face: // For each point p for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) { - Point p = (use_perturbed_points ? compute_perturbed_point(i) : *it_p); + Point p = point_projection( + use_perturbed_points ? compute_perturbed_point(i) : *it_p); for (int ii = 0 ; ii < N ; ++ii) { int i = 0; -#if BETTER_EXPORT_FOR_FLAT_TORUS +#if CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS // For flat torus os << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 2)) << " " << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 3)) << " " @@ -4104,11 +4287,17 @@ next_face: star_using_triangles.end(); for ( ; it_simplex != it_simplex_end ; ++it_simplex) { - // Don't export infinite cells - if (is_infinite(it_simplex->first)) - continue; - const Indexed_simplex &c = it_simplex->first; + + // Don't export infinite cells + if (is_infinite(c)) + continue; + +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(c, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + continue; +#endif + int color_simplex = it_simplex->second; std::stringstream sstr_c; @@ -4285,6 +4474,11 @@ public: // Don't export infinite cells if (is_infinite(*it_tri)) continue; + +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(*it_tri, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + continue; +#endif os << 3 << " "; Indexed_simplex::const_iterator it_point_idx = it_tri->begin(); @@ -4427,6 +4621,7 @@ private: Tr_container m_triangulations; // Contains the triangulations // and their center vertex Stars_container m_stars; + std::vector m_squared_star_spheres_radii_incl_margin; #ifdef CGAL_LINKED_WITH_TBB //std::vector m_tr_mutexes; #endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 6a273ce28fe..293b61fa520 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -88,6 +88,21 @@ public: m_tree.build(); } + /// Constructor + template + Point_cloud_data_structure( + Point_container_ const& points, + Point_indices_range const& only_these_points) + : m_points(points), + m_tree( + only_these_points.begin(), only_these_points.end(), + typename Tree::Splitter(), + STraits((Point*)&(points[0]))) + { + // Build the tree now (we don't want to wait for the first query) + m_tree.build(); + } + /// Constructor Point_cloud_data_structure( Point_container_ const& points, diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index e1472ae8d95..ecaf69a734b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -371,6 +371,119 @@ namespace Tangential_complex_ { return output_basis; } + // Functor to compute radial projection from R^4 to S^3(sphere_radius) + // The returned point coordinates are expressed with the origin + // at `center_of_sphere`, i.e. the new points are all on the sphere + // S^3{(0,0,0,0), sphere_radius} + template + class R4_to_S3_radial_projection + { + public: + typedef typename K::FT FT; + typedef typename K::Point_d Point; + + // center_of_projection will be sent to infinity by the projection + R4_to_S3_radial_projection( + FT sphere_radius, Point const& center_of_sphere, K const& k) + : m_sphere_radius(sphere_radius), m_center_of_sphere(center_of_sphere), + m_k(k) {} + + Point operator()(Point const& p) const + { + CGAL_assertion(m_k.point_dimension_d_object()(p) == 4); + + typedef K::FT FT; + typedef K::Point_d Point; + typedef K::Vector_d Vector; + + typename K::Translated_point_d transl = m_k.translated_point_d_object(); + typename K::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); + typename K::Vector_to_point_d vec_to_pt = m_k.vector_to_point_d_object(); + typename K::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + + Point transl_p = transl(p, scaled_vec(pt_to_vec(m_center_of_sphere), FT(-1))); + Vector v = pt_to_vec(transl_p); + v = scaled_vec(v, m_sphere_radius / CGAL::sqrt(sqlen(v))); + + return vec_to_pt(v); + } + + private: + FT m_sphere_radius; + Point m_center_of_sphere; + K const& m_k; + }; + + // Functor to compute stereographic projection from S^3(sphere_radius) to R^3 + template + class S3_to_R3_stereographic_projection + { + public: + typedef typename K::FT FT; + typedef typename K::Point_d Point; + + // center_of_projection will be sent to infinity by the projection + S3_to_R3_stereographic_projection( + FT sphere_radius, Point const& center_of_projection, K const& k) + : m_sphere_radius(sphere_radius), m_center_of_proj(center_of_projection), + m_k(k) {} + + Point operator()(Point const& p) const + { + CGAL_assertion(m_k.point_dimension_d_object()(p) == 4); + + typedef K::FT FT; + typedef K::Point_d Point; + + typename K::Construct_point_d constr_pt = m_k.construct_point_d_object(); + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); + + std::vector stereo_proj; + stereo_proj.reserve(3); + + FT t = (2 * m_sphere_radius + coord(m_center_of_proj, 3)) + / (m_sphere_radius - (coord(p, 3) - coord(m_center_of_proj, 3))); + for (int i = 0 ; i < 3 ; ++i) + stereo_proj.push_back(coord(m_center_of_proj, i) + t*(coord(p, i) - coord(m_center_of_proj, i))); + + return constr_pt(3, stereo_proj.begin(), stereo_proj.end()); + } + + private: + FT m_sphere_radius; + Point m_center_of_proj; + K const& m_k; + }; + + // Functor to project R^4 points to R^3 + template + class R4_to_R3_using_radial_then_stereographic_projection + { + public: + typedef typename K::FT FT; + typedef typename K::Point_d Point; + + // sphere_radius and center_of_projection are for the stereographic + // projection + R4_to_R3_using_radial_then_stereographic_projection( + FT sphere_radius, Point const& center_of_sphere, + Point const& center_of_projection, K const& k) + : m_R4toS3(sphere_radius, center_of_sphere, k), + m_S3toR3(sphere_radius, center_of_projection, k), + m_k(k) {} + + Point operator()(Point const& p) const + { + return m_S3toR3(m_R4toS3(p)); + } + + private: + R4_to_S3_radial_projection m_R4toS3; + S3_to_R3_stereographic_projection m_S3toR3; + K const& m_k; + }; + // CJTODO: use CGAL::Combination_enumerator (cf. Tangential_complex.h) // Compute all the k-combinations of elements // Output_iterator::value_type must be std::set > From bbfcb5baa290191f0cb1342d6294c7246a74cd37 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 3 Feb 2016 18:19:12 +0100 Subject: [PATCH 402/487] Improve console output & checks + missing include --- .../Tangential_complex/benchmark_tc.cpp | 99 ++- .../include/CGAL/Tangential_complex.h | 382 ++++++------ .../Tangential_complex/Simplicial_complex.h | 55 +- .../CGAL}/Tangential_complex/console_color.h | 13 + .../CGAL/Tangential_complex/protected_sets.h | 564 ++++++++++++++++++ 5 files changed, 855 insertions(+), 258 deletions(-) rename Tangential_complex/{benchmark => include/CGAL}/Tangential_complex/console_color.h (83%) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/protected_sets.h diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index b7dc7484bf5..f9462605ce5 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -13,7 +13,6 @@ #include #include "../../test/Tangential_complex/testing_utilities.h" -#include "console_color.h" #include #include @@ -320,7 +319,7 @@ void make_tc(std::vector &points, std::size_t num_points_before = points.size(); points = sparsify_point_set(k, points, sparsity*sparsity); std::cerr << "Number of points before/after sparsification: " - << num_points_before << " / " << points.size() << std::endl; + << num_points_before << " / " << points.size() << "\n"; } #ifdef TC_PROTECT_POINT_SET_DELTA @@ -338,7 +337,7 @@ void make_tc(std::vector &points, # ifdef CGAL_TC_PROFILING std::cerr << "Point set protected in " << t_protection.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; # endif std::cerr << "Number of points after PROTECTION: " << points.size() << "\n"; @@ -446,12 +445,15 @@ void make_tc(std::vector &points, //tc.check_correlation_between_inconsistencies_and_fatness(); - // CJTODO TEMP - std::cerr << red << "FINAL CHECK:\n" << white; - tc.number_of_inconsistent_simplices(true); - tc.refresh_tangential_complex(); - tc.number_of_inconsistent_simplices(true); - // CJTODO + // DEBUGGING: confirm that all stars were actually refreshed + //std::cerr << yellow << "FINAL CHECK...\n" << white; + //std::size_t num_inc = tc.number_of_inconsistent_simplices(true).second; + //tc.refresh_tangential_complex(); + //if (tc.number_of_inconsistent_simplices(true).second != num_inc) + // std::cerr << red << "FINAL CHECK: FAILED.\n" << white; + //else + // std::cerr << green << "FINAL CHECK: PASSED.\n" << white; + //========================================================================= // Export to OFF @@ -492,9 +494,7 @@ void make_tc(std::vector &points, tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); #endif fix2_time = t.elapsed(); t.reset(); - std::cerr << "Exporting the TC as a Simplicial_complex... "; max_dim = tc.export_TC(complex, false); - std::cerr << "done.\n"; /*std::set > not_delaunay_simplices; if (ambient_dim <= 4) { @@ -513,23 +513,20 @@ void make_tc(std::vector &points, } else { - std::cerr << "Exporting the TC as a Simplicial_complex... "; max_dim = tc.export_TC(complex, false); - std::cerr << "done.\n"; } - std::cerr << "Computing stats of the complex...\n"; complex.display_stats(); if (intrinsic_dim == 2) { - std::cerr << "Computing Euler characteristic of the complex...\n"; + std::cerr << "\nComputing Euler characteristic of the complex...\n"; std::size_t num_vertices = complex.num_K_simplices<0>(); std::size_t num_edges = complex.num_K_simplices<1>(); std::size_t num_triangles = complex.num_K_simplices<2>(); std::cerr << "Euler characteristic: V - E + F = " << num_vertices << " - " << num_edges << " + " << num_triangles << " = " - << yellow + << blue << (std::ptrdiff_t) num_vertices - (std::ptrdiff_t) num_edges + (std::ptrdiff_t) num_triangles @@ -549,7 +546,10 @@ void make_tc(std::vector &points, // Collapse //=========================================================================== if (collapse) + { complex.collapse(max_dim); + complex.display_stats(); + } //=========================================================================== // Is the result a pure pseudomanifold? @@ -567,9 +567,6 @@ void make_tc(std::vector &points, &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, &unconnected_stars_simplices); - // Stats about the simplices - complex.display_stats(); - //=========================================================================== // Export to OFF //=========================================================================== @@ -583,10 +580,10 @@ void make_tc(std::vector &points, &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, &unconnected_stars_simplices); std::cerr - << " OFF colors:" << std::endl - << " * Red: wrong dim simplices" << std::endl - << " * Green: wrong number of cofaces simplices" << std::endl - << " * Blue: not-connected stars" << std::endl; + << " OFF colors:\n" + << " * Red: wrong dim simplices\n" + << " * Green: wrong number of cofaces simplices\n" + << " * Blue: not-connected stars\n"; double export_after_collapse_time = (exported ? t.elapsed() : -1.); t.reset(); } @@ -595,26 +592,23 @@ void make_tc(std::vector &points, // Display info //=========================================================================== - std::cerr << std::endl - << "================================================" << std::endl - << "Number of vertices: " << tc.number_of_vertices() << std::endl - << "Pure pseudomanifold: " << yellow - << (is_pure_pseudomanifold ? "YES" : "NO") << white << std::endl - << "Computation times (seconds): " << std::endl - << " * Tangential complex: " << init_time + computation_time << std::endl - << " - Init + kd-tree = " << init_time << std::endl - << " - TC computation = " << computation_time << std::endl - << " * Export to OFF (before perturb): " << export_before_time << std::endl + std::cerr + << "\n================================================\n" + << "Number of vertices: " << tc.number_of_vertices() << "\n" + << "Computation times (seconds): \n" + << " * Tangential complex: " << init_time + computation_time << "\n" + << " - Init + kd-tree = " << init_time << "\n" + << " - TC computation = " << computation_time << "\n" + << " * Export to OFF (before perturb): " << export_before_time << "\n" << " * Fix inconsistencies 1: " << perturb_time << " (" << num_perturb_steps << " steps) ==> " - << (perturb_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl - << " * Fix inconsistencies 2: " << fix2_time << std::endl - << " * Export to OFF (after perturb): " << export_after_perturb_time << std::endl - << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl + << (perturb_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << "\n" + << " * Fix inconsistencies 2: " << fix2_time << "\n" + << " * Export to OFF (after perturb): " << export_after_perturb_time << "\n" + << " * Export to OFF (after fix2): "<< export_after_fix2_time << "\n" << " * Export to OFF (after collapse): " - << export_after_collapse_time << std::endl - << "================================================" << std::endl - << std::endl; + << export_after_collapse_time << "\n" + << "================================================\n"; //=========================================================================== // Export info @@ -651,7 +645,7 @@ int main() unsigned int seed = static_cast(time(NULL)); CGAL::default_random = CGAL::Random(seed); - std::cerr << "Random seed = " << seed << std::endl; + std::cerr << "Random seed = " << seed << "\n"; std::ifstream script_file; script_file.open(BENCHMARK_SCRIPT_FILENAME); @@ -680,7 +674,7 @@ int main() num_threads > 0 ? num_threads : tbb::task_scheduler_init::automatic); #endif - std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' found." << std::endl; + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' found.\n"; script_file.seekg(0); while (script_file.good()) { @@ -690,10 +684,10 @@ int main() { boost::replace_all(line, "\t", " "); boost::trim_all(line); - std::cerr << std::endl << std::endl; - std::cerr << "*****************************************" << std::endl; - std::cerr << "******* " << line << std::endl; - std::cerr << "*****************************************" << std::endl; + std::cerr << "\n\n"; + std::cerr << "*****************************************\n"; + std::cerr << "******* " << line << "\n"; + std::cerr << "*****************************************\n"; std::stringstream sstr(line); std::string input; @@ -747,7 +741,7 @@ int main() CGAL_TC_SET_PERFORMANCE_DATA("Num_threads", "N/A"); #endif - std::cerr << std::endl << "TC #" << i << "..." << std::endl; + std::cerr << "\nTC #" << i << "...\n"; #ifdef CGAL_TC_PROFILING Wall_clock_timer t_gen; @@ -833,7 +827,7 @@ int main() #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated/loaded in " << t_gen.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; #endif if (!points.empty()) @@ -850,13 +844,12 @@ int main() sparsity, perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', time_limit_for_perturb, input.c_str()); - std::cerr << "TC #" << i++ << " done." << std::endl; - std::cerr << std::endl << "---------------------------------" - << std::endl << std::endl; + std::cerr << "TC #" << i++ << " done.\n"; + std::cerr << "\n---------------------------------\n"; } else { - std::cerr << "TC #" << i++ << ": no points loaded." << std::endl; + std::cerr << "TC #" << i++ << ": no points loaded.\n"; } XML_perf_data::commit(); @@ -872,7 +865,7 @@ int main() // Or not script? else { - std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found." << std::endl; + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found.\n"; } system("pause"); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 669ce57f4f8..70efc0ec772 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -26,6 +26,7 @@ #include #include #include +#include "CGAL/Tangential_complex/console_color.h" #include #include @@ -86,13 +87,13 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE //#define CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS -//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 0.96 +#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 1.9 // 0.95 namespace CGAL { using namespace Tangential_complex_; -enum Fix_inconsistencies_status { +enum Fix_inconsistencies_status { TC_FIXED = 0, TIME_LIMIT_REACHED, FIX_NOT_PERFORMED }; class Vertex_data @@ -371,7 +372,7 @@ public: { #ifdef CGAL_TC_PERTURB_TANGENT_SPACE std::cerr << "Cannot use CGAL_TC_PERTURB_TANGENT_SPACE and set " - << " tangent spaces manually at the same time" << std::endl; + << " tangent spaces manually at the same time\n"; std::exit(EXIT_FAILURE); #endif #ifdef CGAL_TC_EXPORT_NORMALS @@ -390,6 +391,11 @@ public: void compute_tangential_complex() { +#ifdef CGAL_TC_PERFORM_EXTRA_CHECKS + std::cerr << red << "WARNING: CGAL_TC_PERFORM_EXTRA_CHECKS is defined." + << "Computation might be slower than usual.\n" << white; +#endif + #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) Wall_clock_timer t; #endif @@ -433,7 +439,7 @@ public: #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) std::cerr << "Tangential complex computed in " << t.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; #endif } @@ -489,6 +495,10 @@ public: void refresh_tangential_complex() { +#if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) + std::cerr << yellow << "\nRefreshing TC... " << white; +#endif + #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif @@ -509,8 +519,10 @@ public: } #ifdef CGAL_TC_PROFILING - std::cerr << "Tangential complex refreshed in " << t.elapsed() - << " seconds." << std::endl; + std::cerr << yellow << "done in " << t.elapsed() + << " seconds.\n" << white; +#elif defined(CGAL_TC_VERBOSE) + std::cerr << yellow << "done.\n" << white; #endif } @@ -519,6 +531,10 @@ public: void refresh_tangential_complex( Point_indices_range const& perturbed_points_indices) { +#if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) + std::cerr << yellow << "\nRefreshing TC... " << white; +#endif + #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif @@ -543,17 +559,19 @@ public: } #ifdef CGAL_TC_PROFILING - std::cerr << "Tangential complex refreshed in " << t.elapsed() - << " seconds." << std::endl; + std::cerr << yellow << "done in " << t.elapsed() + << " seconds.\n" << white; +#elif defined(CGAL_TC_VERBOSE) + std::cerr << yellow << "done.\n" << white; #endif } // time_limit in seconds: 0 = no fix to do, < 0 = no time limit Fix_inconsistencies_status fix_inconsistencies_using_perturbation( unsigned int &num_steps, - std::size_t &initial_num_inconsistent_local_tr, - std::size_t &best_num_inconsistent_local_tr, - std::size_t &final_num_inconsistent_local_tr, + std::size_t &initial_num_inconsistent_stars, + std::size_t &best_num_inconsistent_stars, + std::size_t &final_num_inconsistent_stars, double time_limit = -1.) { if (time_limit == 0.) @@ -561,34 +579,46 @@ public: Wall_clock_timer t; -#ifdef CGAL_TC_VERBOSE - std::cerr << "Fixing inconsistencies..." << std::endl; -#endif - #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES std::pair stats_before = number_of_inconsistent_simplices(false); # ifdef CGAL_TC_VERBOSE std::cerr << "Initial number of inconsistencies: " - << stats_before.second << std::endl; + << stats_before.second << "\n"; # endif if (stats_before.second == 0) { # ifdef CGAL_TC_VERBOSE - std::cerr << "Nothing to fix." << std::endl; + std::cerr << "Nothing to fix.\n"; # endif return TC_FIXED; } #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES bool done = false; - best_num_inconsistent_local_tr = m_triangulations.size(); + best_num_inconsistent_stars = m_triangulations.size(); num_steps = 0; while (!done) { - std::size_t num_inconsistent_local_tr = 0; +#ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES + std::cerr + << "\nBefore fix step:\n" + << " * Total number of simplices in stars (incl. duplicates): " + << stats_before.first << "\n" + << " * Num inconsistent simplices in stars (incl. duplicates): " + << red << stats_before.second << white + << " (" << 100. * stats_before.second / stats_before.first << "%)\n"; +#endif + +#if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) + std::cerr << yellow + << "\nAttempt to fix inconsistencies using perturbations - step #" + << num_steps + 1 << "... " << white; +#endif + + std::size_t num_inconsistent_stars = 0; std::vector updated_points; #ifdef CGAL_TC_PROFILING @@ -606,7 +636,7 @@ public: Try_to_solve_inconsistencies_in_a_local_triangulation( *this, num_inconsistencies, tls_updated_points) ); - num_inconsistent_local_tr = + num_inconsistent_stars = num_inconsistencies.combine(std::plus()); updated_points = tls_updated_points.combine( [](std::vector const& x, std::vector const& y) { // CJTODO: C++11 @@ -623,93 +653,83 @@ public: { for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) { - num_inconsistent_local_tr += + num_inconsistent_stars += try_to_solve_inconsistencies_in_a_local_triangulation( i, std::back_inserter(updated_points)); } } + double fix_step_time = t_fix_step.elapsed(); + +#if defined(CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES) || defined(CGAL_TC_VERBOSE) + std::cerr + << "\nEncountered during fix:\n" + << " * Num stars containing inconsistent simplices: " + << red << num_inconsistent_stars << white + << " (" << 100. * num_inconsistent_stars / m_points.size() << "%)\n"; +#endif + #ifdef CGAL_TC_PROFILING - std::cerr << "Attempt to fix inconsistencies: " << t_fix_step.elapsed() - << " seconds." << std::endl; + std::cerr << yellow << "done in " << fix_step_time + << " seconds.\n" << white; +#elif defined(CGAL_TC_VERBOSE) + std::cerr << yellow << "done.\n" << white; #endif #ifdef CGAL_TC_GLOBAL_REFRESH - if (num_inconsistent_local_tr > 0) + if (num_inconsistent_stars > 0) refresh_tangential_complex(updated_points); + +# ifdef CGAL_TC_PERFORM_EXTRA_CHECKS + // DEBUGGING: confirm that all stars were actually refreshed + std::size_t num_inc_1 = number_of_inconsistent_simplices(false).second; + refresh_tangential_complex(); + std::size_t num_inc_2 = number_of_inconsistent_simplices(false).second; + if (num_inc_1 != num_inc_2) + std::cerr << red << "REFRESHMENT CHECK: FAILED. (" + << num_inc_1 << " vs " << num_inc_2 << ")\n" << white; + else + std::cerr << green << "REFRESHMENT CHECK: PASSED.\n" << white; +# endif #endif #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES - if (num_inconsistent_local_tr > 0) - { - std::pair stats_after = - number_of_inconsistent_simplices(false); + std::pair stats_after = + number_of_inconsistent_simplices(false); - std::cerr << std::endl - << "==========================================================" - << std::endl - << "Inconsistencies (detailed stats):\n" - << " * Number of vertices: " << m_points.size() << std::endl - << std::endl - << " * BEFORE fix_inconsistencies_using_perturbation:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " - << stats_before.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second - << " (" << 100. * stats_before.second / stats_before.first << "%)" - << std::endl - /*<< " * Num inconsistent stars: " - << num_inconsistent_local_tr - << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" - << std::endl*/ - << std::endl - << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second - << " (" << 100. * stats_after.second / stats_after.first << "%)" - << std::endl - << "==========================================================" - << std::endl; + std::cerr + << "\nAfter fix:\n" + << " * Total number of simplices in stars (incl. duplicates): " + << stats_after.first << "\n" + << " * Num inconsistent simplices in stars (incl. duplicates): " + << red << stats_after.second << white + << " (" << 100. * stats_after.second / stats_after.first << "%)\n"; - stats_before = stats_after; - } - -#else // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -# ifdef CGAL_TC_VERBOSE - std::cerr << std::endl - << "==========================================================" - << std::endl - << "fix_inconsistencies_using_perturbation():\n" - << " * " << m_points.size() << " vertices" << std::endl - << " * " << num_inconsistent_local_tr - << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" - << " inconsistent stars encountered" << std::endl - << "==========================================================" - << std::endl; -# endif -#endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES + stats_before = stats_after; +#endif if (num_steps == 0) - initial_num_inconsistent_local_tr = num_inconsistent_local_tr; + initial_num_inconsistent_stars = num_inconsistent_stars; - if (num_inconsistent_local_tr < best_num_inconsistent_local_tr) - best_num_inconsistent_local_tr = num_inconsistent_local_tr; + if (num_inconsistent_stars < best_num_inconsistent_stars) + best_num_inconsistent_stars = num_inconsistent_stars; - final_num_inconsistent_local_tr = num_inconsistent_local_tr; + final_num_inconsistent_stars = num_inconsistent_stars; ++num_steps; - done = (num_inconsistent_local_tr == 0); + done = (num_inconsistent_stars == 0); if (!done && time_limit > 0. && t.elapsed() > time_limit) { #ifdef CGAL_TC_VERBOSE - std::cerr << "Time limit reached." << std::endl; + std::cerr << red << "Time limit reached.\n" << white; #endif return TIME_LIMIT_REACHED; } } +#ifdef CGAL_TC_VERBOSE + std::cerr << green << "Fixed!\n" << white; +#endif return TC_FIXED; } @@ -748,19 +768,17 @@ public: if (verbose) { - std::cerr << std::endl - << "==========================================================" - << std::endl + std::cerr + << "\n==========================================================\n" << "Inconsistencies:\n" - << " * Number of vertices: " << m_points.size() << std::endl + << " * Number of vertices: " << m_points.size() << "\n" << " * Total number of simplices in stars (incl. duplicates): " - << num_simplices << std::endl + << num_simplices << "\n" << " * Number of inconsistent simplices in stars (incl. duplicates): " - << num_inconsistent_simplices << std::endl + << num_inconsistent_simplices << "\n" << " * Percentage of inconsistencies: " - << 100. * num_inconsistent_simplices / num_simplices << "%" << std::endl - << "==========================================================" - << std::endl; + << 100. * num_inconsistent_simplices / num_simplices << "%\n" + << "==========================================================\n"; } return std::make_pair(num_simplices, num_inconsistent_simplices); @@ -770,6 +788,14 @@ public: int export_TC(Simplicial_complex &complex, bool export_infinite_simplices = false) const { +#if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) + std::cerr << yellow + << "\nExporting the TC as a Simplicial_complex... " << white; +#endif +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif + int max_dim = -1; // For each triangulation @@ -792,6 +818,14 @@ public: complex.add_simplex(c); } } + +#ifdef CGAL_TC_PROFILING + std::cerr << yellow << "done in " << t.elapsed() + << " seconds.\n" << white; +#elif defined(CGAL_TC_VERBOSE) + std::cerr << yellow << "done.\n" << white; +#endif + return max_dim; } @@ -824,12 +858,11 @@ public: number_of_inconsistent_simplices(false); std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl + << stats_after.first << "\n" << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << std::endl + << stats_after.second << "\n" << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%" - << std::endl; + << 100. * stats_after.second / stats_after.first << "%\n"; } // Returns true if some inconsistencies were found @@ -840,12 +873,11 @@ public: number_of_inconsistent_simplices(false); std::cerr << "BEFORE check_and_solve_inconsistencies_by_filtering_simplices_out():\n" << " - Total number of simplices in stars (incl. duplicates): " - << stats_before.first << std::endl + << stats_before.first << "\n" << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second << std::endl + << stats_before.second << "\n" << " - Percentage of inconsistencies: " - << 100. * stats_before.second / stats_before.first << "%" - << std::endl; + << 100. * stats_before.second / stats_before.first << "%\n"; bool inconsistencies_found = false; @@ -861,12 +893,11 @@ public: number_of_inconsistent_simplices(false); std::cerr << "AFTER check_and_solve_inconsistencies_by_filtering_simplices_out():\n" << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl + << stats_after.first << "\n" << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << std::endl + << stats_after.second << "\n" << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%" - << std::endl; + << 100. * stats_after.second / stats_after.first << "%\n"; return inconsistencies_found; } @@ -1024,7 +1055,7 @@ public: #endif #ifdef CGAL_TC_VERBOSE - std::cerr << "Fixing inconsistencies using alpha TC..." << std::endl; + std::cerr << "Fixing inconsistencies using alpha TC...\n"; #endif //------------------------------------------------------------------------- @@ -1054,9 +1085,9 @@ public: << "Num inconsistent simplices found when filling the priority queues: " << num_inconsistent_simplices; # ifdef CGAL_TC_PROFILING - std::cerr << " (" << t_pq.elapsed() << " s)" << std::endl; + std::cerr << " (" << t_pq.elapsed() << " s)\n"; # endif - std::cerr << std::endl; + std::cerr << "\n"; #endif //------------------------------------------------------------------------- @@ -1157,7 +1188,7 @@ public: if (is_simplex_in_star(ii, z)) { is_this_simplex_somewhere = true; - std::cerr << "The simplex is in star #" << ii << std::endl; + std::cerr << "The simplex is in star #" << ii << "\n"; break; } } @@ -1168,28 +1199,28 @@ public: if (m_ambient_dim <= 3) { if (is_simplex_in_the_ambient_delaunay(full_s)) - std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + std::cerr << "The simplex is in the ambiant Delaunay.\n"; else - std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + std::cerr << "The simplex is NOT in the ambiant Delaunay.\n"; std::cerr << "Checking simplices of the star #" - << saa.m_center_point_index << std::endl; + << saa.m_center_point_index << "\n"; Star const& star = m_stars[saa.m_center_point_index]; for (Star::const_iterator is = star.begin(), is_end = star.end() ; is != is_end ; ++is) { if (is_simplex_in_the_ambient_delaunay(*is)) - std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + std::cerr << "The simplex is in the ambiant Delaunay.\n"; else { - std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + std::cerr << "The simplex is NOT in the ambiant Delaunay.\n"; for(auto ii : *is) // CJTODO C++11 perturb(ii); } } } - std::cerr << "Perturbing the points..." << std::endl; + std::cerr << "Perturbing the points...\n"; perturb(saa.m_center_point_index); for(auto ii : saa.m_simplex) // CJTODO C++11 perturb(ii); @@ -1205,7 +1236,7 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Num inconsistent simplices found when filling the priority queues: " - << num_inconsistent_simplices << std::endl; + << num_inconsistent_simplices << "\n"; #endif } // CJTODO TEMP @@ -1234,7 +1265,7 @@ public: #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex fixed in " << t.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; #endif } #endif // CGAL_ALPHA_TC @@ -1267,27 +1298,22 @@ public: if (m_ambient_dim < 2) { - std::cerr << "Error: export_to_off => ambient dimension should be >= 2." - << std::endl; - os << "Error: export_to_off => ambient dimension should be >= 2." - << std::endl; + std::cerr << "Error: export_to_off => ambient dimension should be >= 2.\n"; + os << "Error: export_to_off => ambient dimension should be >= 2.\n"; return os; } if (m_ambient_dim > 3) { std::cerr << "Warning: export_to_off => ambient dimension should be " - "<= 3. Only the first 3 coordinates will be exported." - << std::endl; + "<= 3. Only the first 3 coordinates will be exported.\n"; } if (m_intrinsic_dim < 1 || m_intrinsic_dim > 3) { std::cerr << "Error: export_to_off => intrinsic dimension should be " - "between 1 and 3." - << std::endl; + "between 1 and 3.\n"; os << "Error: export_to_off => intrinsic dimension should be " - "between 1 and 3." - << std::endl; + "between 1 and 3.\n"; return os; } @@ -1542,16 +1568,15 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << (incorrect_simplices->empty() ? "OK " : "ERROR ") - << "check_if_all_simplices_are_in_the_ambient_delaunay:" - << std::endl + << "check_if_all_simplices_are_in_the_ambient_delaunay:\n" << " Number of simplices in ambient RT: " << amb_dt_simplices.size() - << std::endl + << "\n" << " Number of unique simplices in TC stars: " << p_simplices->size() - << std::endl + << "\n" << " Number of infinite full cells in TC stars: " << num_infinite_cells - << std::endl + << "\n" << " Number of wrong simplices: " << incorrect_simplices->size() - << std::endl; + << "\n"; #endif return incorrect_simplices->empty(); } @@ -1657,6 +1682,10 @@ private: for (Indexed_simplex::const_iterator it_index = s.begin(); it_index != s.end() ; ++it_index) { + // Infinite vertex? Much too far! + if (*it_index == std::numeric_limits::max()) + return true; + if (is_one_of_the_coord_far_from_origin( compute_perturbed_point(*it_index), limit, only_test_the_first_n_coords)) return true; @@ -1707,7 +1736,7 @@ private: center_vertex = triangulation.insert(proj_wp); center_vertex->data() = i; if (verbose) - std::cerr << "* Inserted point #" << i << std::endl; + std::cerr << "* Inserted point #" << i << "\n"; #ifdef CGAL_TC_VERY_VERBOSE std::size_t num_attempts_to_insert_points = 1; @@ -1797,7 +1826,7 @@ private: ++num_inserted_points; #endif if (verbose) - std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; + std::cerr << "* Inserted point #" << neighbor_point_idx << "\n"; vh->data() = neighbor_point_idx; @@ -1876,7 +1905,7 @@ private: std::size_t i, Points_ds const& updated_pts_ds, bool verbose = false) { if (verbose) - std::cerr << "** Refreshing tangent tri #" << i << " **" << std::endl; + std::cerr << "** Refreshing tangent tri #" << i << " **\n"; if (m_squared_star_spheres_radii_incl_margin[i] == FT(-1)) return compute_tangent_triangulation(i, verbose); @@ -1905,8 +1934,8 @@ private: void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) - std::cerr << "** Computing tangent tri #" << i << " **" << std::endl; - //std::cerr << "***********************************************" << std::endl; + std::cerr << "** Computing tangent tri #" << i << " **\n"; + //std::cerr << "***********************************************\n"; // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions @@ -1915,7 +1944,7 @@ private: #if defined(CGAL_TC_VERY_VERBOSE) && defined(CGAL_ALPHA_TC) std::cerr << "Base dimension, incl. thickening vectors: " - << tsb.dimension() << std::endl; + << tsb.dimension() << "\n"; #endif // Estimate the tangent space if (!m_are_tangent_spaces_computed[i]) @@ -2405,7 +2434,7 @@ next_face: //Vector n = m_k.point_to_vector_d_object()(p); //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); - //std::cerr << "IP = " << scalar_pdct(n, ts[0]) << " & " << scalar_pdct(n, ts[1]) << std::endl; + //std::cerr << "IP = " << scalar_pdct(n, ts[0]) << " & " << scalar_pdct(n, ts[1]) << "\n"; return tsb; @@ -3387,7 +3416,7 @@ next_face: for (i = 0 ; i < num_coords ; ++i) os << " " << CGAL::to_double(coord(*it_os->begin(), i)); #endif - os << std::endl; + os << "\n"; } #ifdef CGAL_TC_EXPORT_NORMALS ++it_os; @@ -3538,7 +3567,7 @@ next_face: std::size_t neighbor_point_idx = nn_it->first; FT point_to_Cp_power_sqdist = k_power_dist( global_Cp, compute_perturbed_weighted_point(neighbor_point_idx)); - //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP + //std::cerr << point_to_Cp_power_sqdist << "\n"; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_Cp_power_sqdist <= FT(0) && inconsistent_simplex.find(neighbor_point_idx) == @@ -3589,13 +3618,13 @@ next_face: switch(sid) { case ON_NEGATIVE_SIDE: - std::cerr << "ON_NEGATIVE_SIDE" << std::endl; // CJTODO TEMP + std::cerr << "ON_NEGATIVE_SIDE\n"; // CJTODO TEMP break; case ON_POSITIVE_SIDE: - std::cerr << "ON_POSITIVE_SIDE" << std::endl; // CJTODO TEMP + std::cerr << "ON_POSITIVE_SIDE\n"; // CJTODO TEMP break; case ON_ORIENTED_BOUNDARY: - std::cerr << "ON_ORIENTED_BOUNDARY" << std::endl; // CJTODO TEMP + std::cerr << "ON_ORIENTED_BOUNDARY\n"; // CJTODO TEMP break; } }*/ @@ -3614,9 +3643,9 @@ next_face: std::cerr << q_idx << " "; std::copy(s.begin(), s.end(), std::ostream_iterator(std::cerr, " ")); - std::cerr << std::endl; + std::cerr << "\n"; } - std::cerr << std::endl; + std::cerr << "\n"; }*/ // CJTODO TEMP DEBUG @@ -3636,7 +3665,7 @@ next_face: k_scalar_pdct(m_orth_spaces[q_idx][0], pq)); csv_stream << inside_pt_indices.size() << " ; "; csv_stream << dot_product_1 << " ; " << dot_product_2; - csv_stream << std::endl; + csv_stream << "\n"; }*/ // CJTODO TEMP DEBUG @@ -3660,8 +3689,8 @@ next_face: std::cerr << dot_products_between_normals << ", "; //csv_stream << " ; " <first; FT point_to_C_power_sqdist = k_power_dist(C, compute_perturbed_weighted_point(neighbor_point_idx)); - //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP + //std::cerr << point_to_Cp_power_sqdist << "\n"; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_C_power_sqdist <= FT(-0.000001) && inconsistent_simplex.find(neighbor_point_idx) == @@ -3824,7 +3853,7 @@ next_face: k_scalar_pdct(m_orth_spaces[*it_point_idx][0], pq)); csv_stream << "0 ; "; csv_stream << dot_product_1 << " ; " << dot_product_2; - csv_stream << std::endl; + csv_stream << "\n"; }*/ } @@ -4329,37 +4358,33 @@ next_face: } } ++num_OFF_simplices; - os << std::endl; + os << "\n"; } if (is_star_inconsistent) ++num_inconsistent_stars; } #ifdef CGAL_TC_VERBOSE - std::cerr << std::endl - << "==========================================================" - << std::endl + std::cerr + << "\n==========================================================\n" << "Export from list of stars to OFF:\n" - << " * Number of vertices: " << m_points.size() << std::endl + << " * Number of vertices: " << m_points.size() << "\n" << " * Total number of maximal simplices: " << num_maximal_simplices - << std::endl; + << "\n"; if (color_inconsistencies) { std::cerr << " * Number of inconsistent stars: " << num_inconsistent_stars << " (" << (m_points.size() > 0 ? - 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)" - << std::endl + 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)\n" << " * Number of inconsistent maximal simplices: " << num_inconsistent_maximal_simplices << " (" << (num_maximal_simplices > 0 ? 100. * num_inconsistent_maximal_simplices / num_maximal_simplices - : 0.) << "%)" - << std::endl; + : 0.) << "%)\n"; } - std::cerr << "==========================================================" - << std::endl; + std::cerr << "==========================================================\n"; #endif return os; @@ -4501,20 +4526,18 @@ public: } ++num_OFF_simplices; - os << std::endl; + os << "\n"; } } #ifdef CGAL_TC_VERBOSE - std::cerr << std::endl - << "==========================================================" - << std::endl + std::cerr + << "\n==========================================================\n" << "Export from complex to OFF:\n" - << " * Number of vertices: " << m_points.size() << std::endl + << " * Number of vertices: " << m_points.size() << "\n" << " * Total number of maximal simplices: " << num_maximal_simplices - << std::endl - << "==========================================================" - << std::endl; + << "\n" + << "==========================================================\n"; #endif return os; @@ -4527,12 +4550,11 @@ public: std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO TEMP if (m_intrinsic_dim < 3) { - std::cerr << std::endl - << "==========================================================" << std::endl - << "check_correlation_between_inconsistencies_and_fatness():" << std::endl - << "Intrinsic dimension should be >= 3." << std::endl - << "==========================================================" << std::endl - << std::endl; + std::cerr + << "\n==========================================================\n" + << "check_correlation_between_inconsistencies_and_fatness():\n" + << "Intrinsic dimension should be >= 3.\n" + << "==========================================================\n\n"; } std::size_t num_consistent_simplices = 0; @@ -4560,13 +4582,13 @@ public: { ++num_inconsistent_simplices; sum_vol_edge_ratio_inconsistent += fatness; - csv_inconsistent << fatness << std::endl; + csv_inconsistent << fatness << "\n"; } else { ++num_consistent_simplices; sum_vol_edge_ratio_consistent += fatness; - csv_consistent << fatness << std::endl; + csv_consistent << fatness << "\n"; } } } @@ -4576,18 +4598,16 @@ public: double avg_vol_edge_ratio_consistent = sum_vol_edge_ratio_consistent / num_consistent_simplices; - std::cerr << std::endl - << "==========================================================" - << std::endl + std::cerr + << "\n==========================================================\n" << "check_correlation_between_inconsistencies_and_fatness()\n" << " * Avg. volume/longest_edge^d ratio of consistent simplices: " << avg_vol_edge_ratio_consistent - << " (" << num_consistent_simplices << " simplices)" << std::endl + << " (" << num_consistent_simplices << " simplices)\n" << " * Avg. volume/longest_edge^d ratio of inconsistent simplices: " << avg_vol_edge_ratio_inconsistent - << " (" << num_inconsistent_simplices << " simplices)" << std::endl - << "==========================================================" - << std::endl; + << " (" << num_inconsistent_simplices << " simplices)\n" + << "==========================================================\n"; } private: diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index a0105521ce4..5c162124af3 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -24,6 +24,7 @@ #include #include +#include "CGAL/Tangential_complex/console_color.h" #include #include @@ -201,18 +202,17 @@ public: #ifdef CGAL_TC_VERBOSE if (!quiet) - std::cerr << "done." << std::endl; + std::cerr << "done.\n"; #endif } void display_stats() const { - std::cerr << "==========================================================\n"; - std::cerr << "Complex stats:\n"; + std::cerr << yellow << "Complex stats:\n" << white; if (m_complex.empty()) { - std::cerr << "No simplices.\n"; + std::cerr << " * No simplices.\n"; } else { @@ -231,11 +231,9 @@ public: it_map != simplex_stats.end() ; ++it_map) { std::cerr << " * " << it_map->first << "-simplices: " - << it_map->second << std::endl; + << it_map->second << "\n"; } } - - std::cerr << "==========================================================\n"; } // verbose_level = 0, 1 or 2 @@ -266,7 +264,7 @@ public: { if (verbose_level >= 2) std::cerr << "Found a simplex with dim = " - << it_simplex->size() - 1 << std::endl; + << it_simplex->size() - 1 << "\n"; ++num_wrong_dim_simplices; } else @@ -304,13 +302,18 @@ public: if (verbose_level >= 1) { - std::cerr << "is_pure_manifold: " << (ret ? "YES" : "NO") << std::endl; - if (!ret) + std::cerr << "Pure pseudo-manifold: "; + if (ret) { - std::cerr << " * Number of wrong dimension simplices: " - << num_wrong_dim_simplices << std::endl - << " * Number of wrong number of cofaces: " - << num_wrong_number_of_cofaces << std::endl; + std::cerr << green << "YES" << white << "\n"; + } + else + { + std::cerr << red << "NO" << white << "\n" + << " * Number of wrong dimension simplices: " + << num_wrong_dim_simplices << "\n" + << " * Number of wrong number of cofaces: " + << num_wrong_number_of_cofaces << "\n"; } } @@ -325,7 +328,7 @@ public: template std::size_t num_K_simplices() const { - std::set k_simplices; + std::set k_simplices; for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; @@ -391,7 +394,7 @@ public: { if (verbose_level >= 2) std::cerr << "Found a simplex with dim = " - << it_simplex->size() - 1 << std::endl; + << it_simplex->size() - 1 << "\n"; ++num_wrong_dim_simplices; if (p_wrong_dim_simplices) p_wrong_dim_simplices->insert(*it_simplex); @@ -487,7 +490,7 @@ public: { if (verbose_level >= 2) std::cerr << "Error: star #" << center_vertex_index - << " is not connected" << std::endl; + << " is not connected\n"; ++num_unconnected_stars; if (p_unconnected_stars_simplices) { @@ -513,16 +516,20 @@ public: if (verbose_level >= 1) { - std::cerr << "is_pure_pseudo_manifold: " - << (ret ? "YES" : "NO") << std::endl; - if (!ret) + std::cerr << "Pure pseudo-manifold: "; + if (ret) { - std::cerr << " * Number of wrong dimension simplices: " - << num_wrong_dim_simplices << std::endl + std::cerr << green << "YES" << white << "\n"; + } + else + { + std::cerr << red << "NO" << white << "\n" + << " * Number of wrong dimension simplices: " + << num_wrong_dim_simplices << "\n" << " * Number of wrong number of cofaces: " - << num_wrong_number_of_cofaces << std::endl + << num_wrong_number_of_cofaces << "\n" << " * Number of not-connected stars: " - << num_unconnected_stars << std::endl; + << num_unconnected_stars << "\n"; } } diff --git a/Tangential_complex/benchmark/Tangential_complex/console_color.h b/Tangential_complex/include/CGAL/Tangential_complex/console_color.h similarity index 83% rename from Tangential_complex/benchmark/Tangential_complex/console_color.h rename to Tangential_complex/include/CGAL/Tangential_complex/console_color.h index 50554178257..69435f3c189 100644 --- a/Tangential_complex/benchmark/Tangential_complex/console_color.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/console_color.h @@ -65,4 +65,17 @@ inline std::ostream& white(std::ostream &s) return s; } +inline std::ostream& black_on_white(std::ostream &s) +{ +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); +#else + s << "\x1b[0;33m"; +#endif + return s; +} + + #endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex/protected_sets.h b/Tangential_complex/include/CGAL/Tangential_complex/protected_sets.h new file mode 100644 index 00000000000..641165edd90 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/protected_sets.h @@ -0,0 +1,564 @@ +#ifndef PROTECTED_SETS_H +#define PROTECTED_SETS_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +typedef CGAL::Epick_d K; +typedef K::FT FT; +typedef K::Point_d Point_d; +typedef K::Vector_d Vector_d; +typedef K::Oriented_side_d Oriented_side_d; +typedef K::Has_on_positive_side_d Has_on_positive_side_d; +typedef K::Sphere_d Sphere_d; +typedef K::Hyperplane_d Hyperplane_d; + +typedef CGAL::Delaunay_triangulation Delaunay_triangulation; +typedef Delaunay_triangulation::Facet Facet; +typedef Delaunay_triangulation::Vertex_handle Delaunay_vertex; +typedef Delaunay_triangulation::Full_cell_handle Full_cell_handle; + +typedef std::vector Point_Vector; +typedef CGAL::Euclidean_distance Euclidean_distance; + +FT _sfty = pow(10,-14); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// AUXILLARY FUNCTIONS +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** Insert a point in Delaunay triangulation. If you are working in a flat torus, the procedure adds all the 3^d copies in adjacent cubes as well + * + * W is the initial point vector + * chosen_landmark is the index of the chosen point in W + * landmarks_ind is the vector of indices of already chosen points in W + * delaunay is the Delaunay triangulation + * landmark_count is the current number of chosen vertices + * torus is true iff you are working on a flat torus [-1,1]^d + * OUT: Vertex handle to the newly inserted point + */ +Delaunay_vertex insert_delaunay_landmark_with_copies(Point_Vector& W, int chosen_landmark, std::vector& landmarks_ind, Delaunay_triangulation& delaunay, int& landmark_count, bool torus) +{ + if (!torus) + { + Delaunay_vertex v =delaunay.insert(W[chosen_landmark]); + landmarks_ind.push_back(chosen_landmark); + landmark_count++; + return v; + } + else + { + int D = W[0].size(); + int nb_cells = pow(3, D); + Delaunay_vertex v; + for (int i = 0; i < nb_cells; ++i) + { + std::vector point; + int cell_i = i; + for (int l = 0; l < D; ++l) + { + point.push_back(W[chosen_landmark][l] + 2.0*(cell_i%3-1)); + cell_i /= 3; + } + v = delaunay.insert(point); + } + landmarks_ind.push_back(chosen_landmark); + landmark_count++; + return v; + } +} + +/** Small check if the vertex v is in the full cell fc + */ + +bool vertex_is_in_full_cell(Delaunay_triangulation::Vertex_handle v, Full_cell_handle fc) +{ + for (auto v_it = fc->vertices_begin(); v_it != fc->vertices_end(); ++v_it) + if (*v_it == v) + return true; + return false; +} + +/** Fill chosen point vector from indices with copies if you are working on a flat torus + * + * IN: W is the point vector + * OUT: landmarks is the output vector + * IN: landmarks_ind is the vector of indices + * IN: torus is true iff you are working on a flat torus [-1,1]^d + */ + +void fill_landmarks(Point_Vector& W, Point_Vector& landmarks, std::vector& landmarks_ind, bool torus) +{ + if (!torus) + for (unsigned j = 0; j < landmarks_ind.size(); ++j) + landmarks.push_back(W[landmarks_ind[j]]); + else + { + int D = W[0].size(); + int nb_cells = pow(3, D); + int nbL = landmarks_ind.size(); + // Fill landmarks + for (int i = 0; i < nb_cells-1; ++i) + for (int j = 0; j < nbL; ++j) + { + int cell_i = i; + Point_d point; + for (int l = 0; l < D; ++l) + { + point.push_back(W[landmarks_ind[j]][l] + 2.0*(cell_i-1)); + cell_i /= 3; + } + landmarks.push_back(point); + } + } +} + +/** Fill a vector of all simplices in the Delaunay triangulation giving integer indices to vertices + * + * IN: t is the Delaunay triangulation + * OUT: full_cells is the output vector + */ + +void fill_full_cell_vector(Delaunay_triangulation& t, std::vector>& full_cells) +{ + // Store vertex indices in a map + int ind = 0; //index of a vertex + std::map index_of_vertex; + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + if (t.is_infinite(v_it)) + continue; + else + index_of_vertex[v_it] = ind++; + // Write full cells as vectors in full_cells + for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it) + { + if (t.is_infinite(fc_it)) + continue; + Point_Vector vertices; + for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it) + vertices.push_back((*fc_v_it)->point()); + Sphere_d cs( vertices.begin(), vertices.end()); + Point_d csc = cs.center(); + bool in_cube = true; + for (auto xi = csc.cartesian_begin(); xi != csc.cartesian_end(); ++xi) + if (*xi > 1.0 || *xi < -1.0) + { + in_cube = false; break; + } + if (!in_cube) + continue; + std::vector cell; + for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it) + cell.push_back(index_of_vertex[*v_it]); + full_cells.push_back(cell); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// IS VIOLATED TEST +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** Check if a newly created cell is protected from old vertices + * + * t is the Delaunay triangulation + * vertices is the vector containing the point to insert and a facet f in t + * v1 is the vertex of t, such that f and v1 form a simplex + * v2 is the vertex of t, such that f and v2 form another simplex + * delta is the protection constant + * power_protection is true iff the delta-power protection is used + */ + +bool new_cell_is_violated(Delaunay_triangulation& t, std::vector& vertices, const Delaunay_vertex& v1, const Delaunay_vertex v2, FT delta, bool power_protection) +{ + assert(vertices.size() == vertices[0].size() || + vertices.size() == vertices[0].size() + 1); //simplex size = d | d+1 + assert(v1 != v2); + if (vertices.size() == vertices[0].size() + 1) + // FINITE CASE + { + Sphere_d cs(vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(Euclidean_distance().transformed_distance(center_cs, vertices[0])); + /* + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + if (!t.is_infinite(v_it)) + { + //CGAL::Oriented_side side = Oriented_side_d()(cs, (v_it)->point()); + if (std::find(vertices.begin(), vertices.end(), v_it->point()) == vertices.end()) + { + FT dist2 = Euclidean_distance().transformed_distance(center_cs, (v_it)->point()); + if (!power_protection) + if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta)) + return true; + if (power_protection) + if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta) + return true; + } + } + */ + if (!t.is_infinite(v1)) + { + FT dist2 = Euclidean_distance().transformed_distance(center_cs, v1->point()); + if (!power_protection) + if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta)) + return true; + if (power_protection) + if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta) + return true; + } + if (!t.is_infinite(v2)) + { + FT dist2 = Euclidean_distance().transformed_distance(center_cs, v2->point()); + if (!power_protection) + if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta)) + return true; + if (power_protection) + if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta) + return true; + } + } + else + // INFINITE CASE + { + Delaunay_triangulation::Vertex_iterator v = t.vertices_begin(); + while (t.is_infinite(v) || std::find(vertices.begin(), vertices.end(), v->point()) == vertices.end()) + v++; + Hyperplane_d facet_plane(vertices.begin(), vertices.end(), v->point(), CGAL::ON_POSITIVE_SIDE); + Vector_d orth_v = facet_plane.orthogonal_vector(); + /* + for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it) + if (!t.is_infinite(v_it)) + if (std::find(vertices.begin(), vertices.end(), v_it->point()) == vertices.end()) + { + std::vector coords; + Point_d p = v_it->point(); + auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin(); + for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i) + coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length())); + Point_d p_delta = Point_d(coords); + bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p); + bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta); + if (!p_is_inside && p_delta_is_inside) + return true; + } + */ + if (!t.is_infinite(v1)) + { + std::vector coords; + Point_d p = v1->point(); + auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin(); + for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i) + coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length())); + Point_d p_delta = Point_d(coords); + bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p); + bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta); + if (!p_is_inside && p_delta_is_inside) + return true; + } + if (!t.is_infinite(v2)) + { + std::vector coords; + Point_d p = v2->point(); + auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin(); + for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i) + coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length())); + Point_d p_delta = Point_d(coords); + bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p); + bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta); + if (!p_is_inside && p_delta_is_inside) + return true; + } + } + return false; +} + +/** Auxillary recursive function to check if the point p violates the protection of the cell c and + * if there is a violation of an eventual new cell + * + * p is the point to insert + * t is the current triangulation + * c is the current cell (simplex) + * parent_cell is the parent cell (simplex) + * index is the index of the facet between c and parent_cell from parent_cell's point of view + * D is the dimension of the triangulation + * delta is the protection constant + * marked_cells is the vector of all visited cells containing p in their circumscribed ball + * power_protection is true iff you are working with delta-power protection + * + * OUT: true iff inserting p hasn't produced any violation so far + */ + +bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, Full_cell_handle c, Full_cell_handle parent_cell, int index, int D, FT delta, std::vector& marked_cells, bool power_protection) +{ + Euclidean_distance ed; + std::vector vertices; + if (!t.is_infinite(c)) + { + // if the cell is finite, we look if the protection is violated + for (auto v_it = c->vertices_begin(); v_it != c->vertices_end(); ++v_it) + vertices.push_back((*v_it)->point()); + Sphere_d cs( vertices.begin(), vertices.end()); + Point_d center_cs = cs.center(); + FT r = sqrt(ed.transformed_distance(center_cs, vertices[0])); + FT dist2 = ed.transformed_distance(center_cs, p); + // if the new point is inside the protection ball of a non conflicting simplex + if (!power_protection) + if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta)) + return true; + if (power_protection) + if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta) + return true; + // if the new point is inside the circumscribing ball : continue violation searching on neighbours + //if (dist2 < r*r) + //if (dist2 < (5*r+delta)*(5*r+delta)) + if (dist2 < r*r) + { + c->tds_data().mark_visited(); + marked_cells.push_back(c); + for (int i = 0; i < D+1; ++i) + { + Full_cell_handle next_c = c->neighbor(i); + if (next_c->tds_data().is_clear() && + is_violating_protection(p, t, next_c, c, i, D, delta, marked_cells, power_protection)) + return true; + } + } + // if the new point is outside the protection sphere + else + { + // facet f is on the border of the conflict zone : check protection of simplex {p,f} + // the new simplex is guaranteed to be finite + vertices.clear(); vertices.push_back(p); + for (int i = 0; i < D+1; ++i) + if (i != index) + vertices.push_back(parent_cell->vertex(i)->point()); + Delaunay_vertex vertex_to_check = t.infinite_vertex(); + for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it) + if (!vertex_is_in_full_cell(*vh_it, parent_cell)) + { + vertex_to_check = *vh_it; break; + } + if (new_cell_is_violated(t, vertices, vertex_to_check, parent_cell->vertex(index), delta, power_protection)) + //if (new_cell_is_violated(t, vertices, vertex_to_check->point(), delta)) + return true; + } + } + else + { + // Inside of the convex hull is + side. Outside is - side. + for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it) + if (!t.is_infinite(*vh_it)) + vertices.push_back((*vh_it)->point()); + Delaunay_triangulation::Vertex_iterator v_it = t.vertices_begin(); + while (t.is_infinite(v_it) || vertex_is_in_full_cell(v_it, c)) + v_it++; + Hyperplane_d facet_plane(vertices.begin(), vertices.end(), v_it->point(), CGAL::ON_POSITIVE_SIDE); + //CGAL::Oriented_side outside = Oriented_side_d()(facet_plane, v_it->point()); + Vector_d orth_v = facet_plane.orthogonal_vector(); + std::vector coords; + auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin(); + for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i) + coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length())); + Point_d p_delta = Point_d(coords); + bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p) && (Oriented_side_d()(facet_plane, p) != CGAL::ZERO); + bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta); + + if (!p_is_inside && p_delta_is_inside) + return true; + //if the cell is infinite we look at the neighbours regardless + if (p_is_inside) + { + c->tds_data().mark_visited(); + marked_cells.push_back(c); + for (int i = 0; i < D+1; ++i) + { + Full_cell_handle next_c = c->neighbor(i); + if (next_c->tds_data().is_clear() && + is_violating_protection(p, t, next_c, c, i, D, delta, marked_cells, power_protection)) + return true; + } + } + else + { + // facet f is on the border of the conflict zone : check protection of simplex {p,f} + // the new simplex is finite if the parent cell is finite + vertices.clear(); vertices.push_back(p); + for (int i = 0; i < D+1; ++i) + if (i != index) + if (!t.is_infinite(parent_cell->vertex(i))) + vertices.push_back(parent_cell->vertex(i)->point()); + Delaunay_vertex vertex_to_check = t.infinite_vertex(); + for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it) + if (!vertex_is_in_full_cell(*vh_it, parent_cell)) + { + vertex_to_check = *vh_it; break; + } + if (new_cell_is_violated(t, vertices, vertex_to_check, parent_cell->vertex(index), delta, power_protection)) + //if (new_cell_is_violated(t, vertices, vertex_to_check->point(), delta)) + return true; + } + } + //c->tds_data().clear_visited(); + //marked_cells.pop_back(); + return false; +} + +/** Checks if inserting the point p in t will make conflicts + * + * p is the point to insert + * t is the current triangulation + * D is the dimension of triangulation + * delta is the protection constant + * power_protection is true iff you are working with delta-power protection + * OUT: true iff inserting p produces a violation of delta-protection. + */ + +bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta, bool power_protection) +{ + Euclidean_distance ed; + Delaunay_triangulation::Vertex_handle v; + Delaunay_triangulation::Face f(t.current_dimension()); + Delaunay_triangulation::Facet ft; + Delaunay_triangulation::Full_cell_handle c; + Delaunay_triangulation::Locate_type lt; + std::vector marked_cells; + c = t.locate(p, lt, f, ft, v); + bool violation_existing_cells = is_violating_protection(p, t, c, c, 0, D, delta, marked_cells, power_protection); + for (Full_cell_handle fc : marked_cells) + fc->tds_data().clear(); + return violation_existing_cells; +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +//!!!!!!!!!!!!! THE INTERFACE FOR LANDMARK CHOICE IS BELOW !!!!!!!!!!// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////// +// LANDMARK CHOICE PROCEDURE +/////////////////////////////////////////////////////////////////////// + +/** Procedure to compute a maximal protected subset from a point cloud. All OUTs should be empty at call. + * + * IN: W is the initial point cloud having type Epick_d::Point_d + * IN: nbP is the size of W + * OUT: landmarks is the output vector for the points + * OUT: landmarks_ind is the output vector for the indices of the selected points in W + * IN: delta is the constant of protection + * OUT: full_cells is the output vector of the simplices in the final Delaunay triangulation + * IN: torus is true iff you are working on a flat torus [-1,1]^d + */ + +void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& landmarks, std::vector& landmarks_ind, FT delta, std::vector>& full_cells, bool torus, bool power_protection) +{ + unsigned D = W[0].size(); + Euclidean_distance ed; + Delaunay_triangulation t(D); + CGAL::Random rand; + int landmark_count = 0; + std::list index_list; + // shuffle the list of indexes (via a vector) + { + std::vector temp_vector; + for (int i = 0; i < nbP; ++i) + temp_vector.push_back(i); + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::shuffle(temp_vector.begin(), temp_vector.end(), std::default_random_engine(seed)); + //CGAL::spatial_sort(temp_vector.begin(), temp_vector.end()); + for (std::vector::iterator it = temp_vector.begin(); it != temp_vector.end(); ++it) + index_list.push_front(*it); + } + if (!torus) + for (unsigned pos1 = 0; pos1 < D+1; ++pos1) + { + std::vector point; + for (unsigned i = 0; i < pos1; ++i) + point.push_back(-1); + if (pos1 != D) + point.push_back(1); + for (unsigned i = pos1+1; i < D; ++i) + point.push_back(0); + assert(point.size() == D); + W[index_list.front()] = Point_d(point); + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count, torus); + index_list.pop_front(); + } + else if (D == 2) + { + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 2; ++j) + { + W[index_list.front()] = Point_d(std::vector{i*0.5, j*1.0}); + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count, torus); + index_list.pop_front(); + W[index_list.front()] = Point_d(std::vector{0.25+i*0.5, 0.5+j}); + insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count, torus); + index_list.pop_front(); + } + } + else + std::cout << "No torus starter available for dim>2\n"; + std::list::iterator list_it = index_list.begin(); + while (list_it != index_list.end()) + { + if (!is_violating_protection(W[*list_it], t, D, delta, power_protection)) + { + // If no conflicts then insert in every copy of T^3 + + insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count, torus); + index_list.erase(list_it); + list_it = index_list.begin(); + /* + // PIECE OF CODE FOR DEBUGGING PURPOSES + + Delaunay_vertex inserted_v = insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count); + if (triangulation_is_protected(t, delta)) + { + index_list.erase(list_it); + list_it = index_list.begin(); + } + else + { //THAT'S WHERE SOMETHING'S WRONG + t.remove(inserted_v); + landmarks_ind.pop_back(); + landmark_count--; + write_delaunay_mesh(t, W[*list_it], is2d); + is_violating_protection(W[*list_it], t_old, D, delta); //Called for encore + } + */ + //std::cout << "index_list_size() = " << index_list.size() << "\n"; + } + else + { + list_it++; + //std::cout << "!!!!!WARNING!!!!! A POINT HAS BEEN OMITTED!!!\n"; + } + //if (list_it != index_list.end()) + // write_delaunay_mesh(t, W[*list_it], is2d); + } + fill_landmarks(W, landmarks, landmarks_ind, torus); + fill_full_cell_vector(t, full_cells); + /* + if (triangulation_is_protected(t, delta)) + std::cout << "Triangulation is ok\n"; + else + { + std::cout << "Triangulation is BAD!! T_T しくしく!\n"; + } + */ + //write_delaunay_mesh(t, W[0], is2d); + //std::cout << t << std::endl; +} + +#endif From 4f7de28d923ab747c1a24003135588bc0d82870a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Feb 2016 10:39:45 +0100 Subject: [PATCH 403/487] Improved console output + faster export_TC --- .../Tangential_complex/benchmark_tc.cpp | 2 +- .../include/CGAL/Tangential_complex.h | 138 ++++++++++-------- .../Tangential_complex/Simplicial_complex.h | 3 + 3 files changed, 81 insertions(+), 62 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index f9462605ce5..48c5c34401c 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -449,7 +449,7 @@ void make_tc(std::vector &points, //std::cerr << yellow << "FINAL CHECK...\n" << white; //std::size_t num_inc = tc.number_of_inconsistent_simplices(true).second; //tc.refresh_tangential_complex(); - //if (tc.number_of_inconsistent_simplices(true).second != num_inc) + //if (CGAL::cpp11::get<1>(tc.number_of_inconsistent_simplices(true)) != num_inc) // std::cerr << red << "FINAL CHECK: FAILED.\n" << white; //else // std::cerr << green << "FINAL CHECK: PASSED.\n" << white; diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 70efc0ec772..2f4408332d0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -580,15 +580,15 @@ public: Wall_clock_timer t; #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES - std::pair stats_before = + CGAL::cpp11::tuple stats_before = number_of_inconsistent_simplices(false); # ifdef CGAL_TC_VERBOSE std::cerr << "Initial number of inconsistencies: " - << stats_before.second << "\n"; + << CGAL::cpp11::get<1>(stats_before) << "\n"; # endif - if (stats_before.second == 0) + if (CGAL::cpp11::get<1>(stats_before) == 0) { # ifdef CGAL_TC_VERBOSE std::cerr << "Nothing to fix.\n"; @@ -606,10 +606,13 @@ public: std::cerr << "\nBefore fix step:\n" << " * Total number of simplices in stars (incl. duplicates): " - << stats_before.first << "\n" + << CGAL::cpp11::get<0>(stats_before) << "\n" << " * Num inconsistent simplices in stars (incl. duplicates): " - << red << stats_before.second << white - << " (" << 100. * stats_before.second / stats_before.first << "%)\n"; + << red << CGAL::cpp11::get<1>(stats_before) << white << " (" + << 100. * CGAL::cpp11::get<1>(stats_before) / CGAL::cpp11::get<0>(stats_before) << "%)\n" + << " * Number of stars containing inconsistent simplices: " + << red << CGAL::cpp11::get<2>(stats_before) << white << " (" + << 100. * CGAL::cpp11::get<2>(stats_before) / m_points.size() << "%)\n"; #endif #if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) @@ -681,10 +684,12 @@ public: refresh_tangential_complex(updated_points); # ifdef CGAL_TC_PERFORM_EXTRA_CHECKS - // DEBUGGING: confirm that all stars were actually refreshed - std::size_t num_inc_1 = number_of_inconsistent_simplices(false).second; + // Confirm that all stars were actually refreshed + std::size_t num_inc_1 = + CGAL::cpp11::get<1>(number_of_inconsistent_simplices(false)); refresh_tangential_complex(); - std::size_t num_inc_2 = number_of_inconsistent_simplices(false).second; + std::size_t num_inc_2 = + CGAL::cpp11::get<1>(number_of_inconsistent_simplices(false)); if (num_inc_1 != num_inc_2) std::cerr << red << "REFRESHMENT CHECK: FAILED. (" << num_inc_1 << " vs " << num_inc_2 << ")\n" << white; @@ -694,16 +699,19 @@ public: #endif #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES - std::pair stats_after = + CGAL::cpp11::tuple stats_after = number_of_inconsistent_simplices(false); std::cerr << "\nAfter fix:\n" << " * Total number of simplices in stars (incl. duplicates): " - << stats_after.first << "\n" + << CGAL::cpp11::get<0>(stats_after) << "\n" << " * Num inconsistent simplices in stars (incl. duplicates): " - << red << stats_after.second << white - << " (" << 100. * stats_after.second / stats_after.first << "%)\n"; + << red << CGAL::cpp11::get<1>(stats_after) << white << " (" + << 100. * CGAL::cpp11::get<1>(stats_after) / CGAL::cpp11::get<0>(stats_after) << "%)\n" + << " * Number of stars containing inconsistent simplices: " + << red << CGAL::cpp11::get<2>(stats_after) << white << " (" + << 100. * CGAL::cpp11::get<2>(stats_after) / m_points.size() << "%)\n"; stats_before = stats_after; #endif @@ -716,14 +724,17 @@ public: final_num_inconsistent_stars = num_inconsistent_stars; - ++num_steps; done = (num_inconsistent_stars == 0); - if (!done && time_limit > 0. && t.elapsed() > time_limit) + if (!done) { + ++num_steps; + if (time_limit > 0. && t.elapsed() > time_limit) + { #ifdef CGAL_TC_VERBOSE - std::cerr << red << "Time limit reached.\n" << white; + std::cerr << red << "Time limit reached.\n" << white; #endif - return TIME_LIMIT_REACHED; + return TIME_LIMIT_REACHED; + } } } @@ -733,8 +744,10 @@ public: return TC_FIXED; } - // Return a pair - std::pair number_of_inconsistent_simplices( + // Return a tuple + // + CGAL::cpp11::tuple + number_of_inconsistent_simplices( #ifdef CGAL_TC_VERBOSE bool verbose = true #else @@ -744,9 +757,12 @@ public: { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; + std::size_t num_inconsistent_stars = 0; // For each triangulation for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { + bool is_star_inconsistent = false; + // For each cell Star::const_iterator it_inc_simplex = m_stars[idx].begin(); Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); @@ -760,10 +776,14 @@ public: c.insert(idx); // Add the missing index if (!is_simplex_consistent(c)) + { ++num_inconsistent_simplices; + is_star_inconsistent = true; + } ++num_simplices; } + num_inconsistent_stars += is_star_inconsistent; } if (verbose) @@ -771,22 +791,32 @@ public: std::cerr << "\n==========================================================\n" << "Inconsistencies:\n" - << " * Number of vertices: " << m_points.size() << "\n" << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << "\n" << " * Number of inconsistent simplices in stars (incl. duplicates): " - << num_inconsistent_simplices << "\n" - << " * Percentage of inconsistencies: " - << 100. * num_inconsistent_simplices / num_simplices << "%\n" + << num_inconsistent_simplices << " (" + << 100. * num_inconsistent_simplices / num_simplices << "%)\n" + << " * Number of stars containing inconsistent simplices: " + << num_inconsistent_stars << " (" + << 100. * num_inconsistent_stars / m_points.size() << "%)\n" << "==========================================================\n"; } - return std::make_pair(num_simplices, num_inconsistent_simplices); + return std::make_tuple( + num_simplices, num_inconsistent_simplices, num_inconsistent_stars); } // Return the max dimension of the simplices + // check_lower_and_higher_dim_simplices : 0 (false), 1 (true), 2 (auto) + // If the check is enabled, the function: + // - won't insert the simplex if it is already in a higher dim simplex + // - will erase any lower-dim simplices that are faces of the new simplex + // "auto" (= 2) will enable the check as a soon as it encounters a + // simplex whose dimension is different from the previous ones. + // N.B.: The check is quite expensive. int export_TC(Simplicial_complex &complex, - bool export_infinite_simplices = false) const + bool export_infinite_simplices = false, + int check_lower_and_higher_dim_simplices = 2) const { #if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) std::cerr << yellow @@ -806,16 +836,35 @@ public: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { + Indexed_simplex c = *it_inc_simplex; + // Don't export infinite cells - if (!export_infinite_simplices && is_infinite(*it_inc_simplex)) + if (!export_infinite_simplices && is_infinite(c)) continue; - Indexed_simplex c = *it_inc_simplex; + // Unusual simplex dim? + if (check_lower_and_higher_dim_simplices == 2 + && max_dim != -1 + && static_cast(c.size()) != max_dim) + { + // Let's activate the check + std::cerr << red << + "Info: check_lower_and_higher_dim_simplices ACTIVATED. " + "Export might be take some time...\n" << white; + check_lower_and_higher_dim_simplices = 1; + } + if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); // Add the missing center vertex c.insert(idx); - complex.add_simplex(c); + +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(c, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + continue; +#endif + + complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1); } } @@ -852,33 +901,11 @@ public: } } while (inconsistencies_found); } - - // CJTODO TEMP - std::pair stats_after = - number_of_inconsistent_simplices(false); - std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << "\n" - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << "\n" - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%\n"; } // Returns true if some inconsistencies were found bool check_and_solve_inconsistencies_by_filtering_simplices_out() { - // CJTODO TEMP - std::pair stats_before = - number_of_inconsistent_simplices(false); - std::cerr << "BEFORE check_and_solve_inconsistencies_by_filtering_simplices_out():\n" - << " - Total number of simplices in stars (incl. duplicates): " - << stats_before.first << "\n" - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second << "\n" - << " - Percentage of inconsistencies: " - << 100. * stats_before.second / stats_before.first << "%\n"; - bool inconsistencies_found = false; // CJTODO: parallel_for??? @@ -888,17 +915,6 @@ public: inconsistencies_found = true; } - // CJTODO TEMP - std::pair stats_after = - number_of_inconsistent_simplices(false); - std::cerr << "AFTER check_and_solve_inconsistencies_by_filtering_simplices_out():\n" - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << "\n" - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << "\n" - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%\n"; - return inconsistencies_found; } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 5c162124af3..15eafae7afc 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -46,6 +46,9 @@ public: typedef std::set Simplex; typedef std::set Simplex_set; + // If perform_checks = true, the function: + // - won't insert the simplex if it is already in a higher dim simplex + // - will erase any lower-dim simplices that are faces of the new simplex void add_simplex( const std::set &s, bool perform_checks = true) { From f2ad04c39a7a7c7f4d8655ed4421d6e4be3c5b67 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Feb 2016 11:07:45 +0100 Subject: [PATCH 404/487] Improved output --- .../Tangential_complex/benchmark_mesh_d.cpp | 49 +++++++++---------- Tangential_complex/include/CGAL/Mesh_d.h | 8 +++ 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp index 0e5aea227d1..0338d46ffeb 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -14,7 +14,6 @@ #include #include "../../test/Tangential_complex/testing_utilities.h" -#include "console_color.h" #include #include @@ -120,7 +119,7 @@ void make_mesh( std::size_t num_points_before = points.size(); points = sparsify_point_set(k, points, sparsity*sparsity); std::cerr << "Number of points before/after sparsification: " - << num_points_before << " / " << points.size() << std::endl; + << num_points_before << " / " << points.size() << "\n"; } //=========================================================================== @@ -186,18 +185,17 @@ void make_mesh( // Display info //=========================================================================== - std::cerr << std::endl - << "================================================" << std::endl - << "Number of vertices: " << mesh.number_of_vertices() << std::endl + std::cerr + << "\n================================================\n" + << "Number of vertices: " << mesh.number_of_vertices() << "\n" << "Pure pseudomanifold: " << yellow - << (is_pure_pseudomanifold ? "YES" : "NO") << white << std::endl - << "Computation times (seconds): " << std::endl - << " * Mesh: " << init_time + computation_time << std::endl - << " - Init + kd-tree = " << init_time << std::endl - << " - Mesh computation = " << computation_time << std::endl - //<< " * Export to OFF : " << export_before_time << std::endl - << "================================================" << std::endl - << std::endl; + << (is_pure_pseudomanifold ? "YES" : "NO") << white << "\n" + << "Computation times (seconds): \n" + << " * Mesh: " << init_time + computation_time << "\n" + << " - Init + kd-tree = " << init_time << "\n" + << " - Mesh computation = " << computation_time << "\n" + //<< " * Export to OFF : " << export_before_time << "\n" + << "================================================\n\n"; } int main() @@ -214,7 +212,7 @@ int main() unsigned int seed = static_cast(time(NULL)); CGAL::default_random = CGAL::Random(seed); - std::cerr << "Random seed = " << seed << std::endl; + std::cerr << "Random seed = " << seed << "\n"; std::ifstream script_file; script_file.open(BENCHMARK_SCRIPT_FILENAME); @@ -241,7 +239,7 @@ int main() #endif std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME - << "' found." << std::endl; + << "' found.\n"; script_file.seekg(0); while (script_file.good()) { @@ -251,10 +249,10 @@ int main() { boost::replace_all(line, "\t", " "); boost::trim_all(line); - std::cerr << std::endl << std::endl; - std::cerr << "*****************************************" << std::endl; - std::cerr << "******* " << line << std::endl; - std::cerr << "*****************************************" << std::endl; + std::cerr << "\n\n"; + std::cerr << "*****************************************\n"; + std::cerr << "******* " << line << "\n"; + std::cerr << "*****************************************\n"; std::stringstream sstr(line); std::string input; @@ -297,7 +295,7 @@ int main() input_stripped = input_stripped.substr( slash_index, input_stripped.find_last_of('.') - slash_index); - std::cerr << std::endl << "Mesh #" << i << "..." << std::endl; + std::cerr << "\nMesh #" << i << "...\n"; #ifdef CGAL_MESH_D_PROFILING Wall_clock_timer t_gen; @@ -381,7 +379,7 @@ int main() #ifdef CGAL_MESH_D_PROFILING std::cerr << "Point set generated/loaded in " << t_gen.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; #endif if (!points.empty()) @@ -398,13 +396,12 @@ int main() points, intrinsic_dim, sparsify == 'Y', sparsity, input.c_str()); - std::cerr << "Mesh #" << i++ << " done." << std::endl; - std::cerr << std::endl << "---------------------------------" - << std::endl << std::endl; + std::cerr << "Mesh #" << i++ << " done.\n"; + std::cerr << "\n---------------------------------\n\n"; } else { - std::cerr << "Mesh #" << i++ << ": no points loaded." << std::endl; + std::cerr << "Mesh #" << i++ << ": no points loaded.\n"; } } } @@ -418,7 +415,7 @@ int main() // Or not script? else { - std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found." << std::endl; + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found.\n"; } system("pause"); diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h index 94ef8b3a613..3d72ea2e4d5 100644 --- a/Tangential_complex/include/CGAL/Mesh_d.h +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -352,6 +352,12 @@ public: m_k.scaled_vector_d_object()( m_k.point_to_vector_d_object()(*intersection), weight)); } + else + { + // CJTODO TEMP DEBUG + std::cerr << std::hex << (unsigned int)&k_face << std::dec + << red << "No intersection" << white << "\n"; + } } if (sum_weights > 0) { @@ -366,6 +372,8 @@ public: Point const& p0 = (*k_face.begin())->point(); for (auto neighbor_vh : nghb) // CJTODO: C++11 { + // If a neighbor is closer than p0 to the average intersection, then + // the average intersection is inside another Voronoi cell if (m_k.squared_distance_d_object()(p0, avg_inters) > m_k.squared_distance_d_object()(neighbor_vh->point(), avg_inters)) { From a1e866eb6d868f7519b1da891c6542ec3806861c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Feb 2016 11:09:04 +0100 Subject: [PATCH 405/487] Add Simplicial_complex::load_simplices_from_OFF + minor changes --- .../Tangential_complex/benchmark_tc.cpp | 14 +--- .../include/CGAL/Tangential_complex.h | 13 ++-- .../Tangential_complex/Simplicial_complex.h | 67 +++++++++++++++++++ 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 48c5c34401c..422a7d9ce26 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -519,19 +519,7 @@ void make_tc(std::vector &points, complex.display_stats(); if (intrinsic_dim == 2) - { - std::cerr << "\nComputing Euler characteristic of the complex...\n"; - std::size_t num_vertices = complex.num_K_simplices<0>(); - std::size_t num_edges = complex.num_K_simplices<1>(); - std::size_t num_triangles = complex.num_K_simplices<2>(); - std::cerr << "Euler characteristic: V - E + F = " - << num_vertices << " - " << num_edges << " + " << num_triangles << " = " - << blue - << (std::ptrdiff_t) num_vertices - - (std::ptrdiff_t) num_edges - + (std::ptrdiff_t) num_triangles - << white << "\n"; - } + complex.euler_characteristic(true); // CJTODO TEMP: Export to OFF with higher-dim simplices colored /*std::set > higher_dim_simplices; diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2f4408332d0..2ba43a69ea7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -87,7 +87,7 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE //#define CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS -#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 1.9 // 0.95 +//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 1.9 // 0.95 namespace CGAL { @@ -392,9 +392,13 @@ public: void compute_tangential_complex() { #ifdef CGAL_TC_PERFORM_EXTRA_CHECKS - std::cerr << red << "WARNING: CGAL_TC_PERFORM_EXTRA_CHECKS is defined." + std::cerr << red << "WARNING: CGAL_TC_PERFORM_EXTRA_CHECKS is defined. " << "Computation might be slower than usual.\n" << white; #endif +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + std::cerr << red << "WARNING: CGAL_TC_ALVAREZ_SURFACE_WINDOW is defined (" + << CGAL_TC_ALVAREZ_SURFACE_WINDOW << ").\n" << white; +#endif #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) Wall_clock_timer t; @@ -583,11 +587,6 @@ public: CGAL::cpp11::tuple stats_before = number_of_inconsistent_simplices(false); -# ifdef CGAL_TC_VERBOSE - std::cerr << "Initial number of inconsistencies: " - << CGAL::cpp11::get<1>(stats_before) << "\n"; -# endif - if (CGAL::cpp11::get<1>(stats_before) == 0) { # ifdef CGAL_TC_VERBOSE diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 15eafae7afc..bda063aa1d9 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -36,6 +36,8 @@ #include #include +#include +#include namespace CGAL { namespace Tangential_complex_ { @@ -90,6 +92,47 @@ public: m_complex.insert(s); } + // Ignore the point coordinates + bool load_simplices_from_OFF(const char *filename) + { + std::ifstream in(filename); + if (!in.is_open()) + { + std::cerr << "Could not open '" << filename << "'" << std::endl; + return false; + } + + std::string line; + std::getline(in, line); // Skip first line + std::size_t num_points, num_triangles, dummy; + in >> num_points; + in >> num_triangles; + std::getline(in, line); // Skip the rest of the line + + // Skip points + for (std::size_t i = 0 ; i < num_points ; ++i) + std::getline(in, line); + + // Read triangles + for (std::size_t i = 0 ; i < num_triangles ; ++i) + { + in >> dummy; + CGAL_assertion(dummy == 3); + std::set tri; + std::size_t idx; + for (int j = 0 ; j < 3 ; ++j) + { + in >> idx; + tri.insert(idx); + } + std::getline(in, line); // Skip the rest of the line + + add_simplex(tri, false); + } + + return true; + } + const Simplex_set &simplex_range() const { return m_complex; @@ -353,6 +396,30 @@ public: return k_simplices.size(); } + std::ptrdiff_t euler_characteristic(bool verbose = false) const + { + if (verbose) + std::cerr << "\nComputing Euler characteristic of the complex...\n"; + + std::size_t num_vertices = num_K_simplices<0>(); + std::size_t num_edges = num_K_simplices<1>(); + std::size_t num_triangles = num_K_simplices<2>(); + + std::ptrdiff_t ec = + (std::ptrdiff_t) num_vertices + - (std::ptrdiff_t) num_edges + + (std::ptrdiff_t) num_triangles; + + if (verbose) + std::cerr << "Euler characteristic: V - E + F = " + << num_vertices << " - " << num_edges << " + " << num_triangles << " = " + << blue + << ec + << white << "\n"; + + return ec; + } + // CJTODO: ADD COMMENTS bool is_pure_pseudomanifold( int simplex_dim, From e84351f14b2c70b902afa8932d8edb7e2755fc44 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Feb 2016 11:10:00 +0100 Subject: [PATCH 406/487] Small app to compute the euler charact from an OFF file --- .../Tangential_complex/CMakeLists.txt | 39 +++++++++++++++++++ .../Tangential_complex/euler_charact.cpp | 19 +++++++++ 2 files changed, 58 insertions(+) create mode 100644 Tangential_complex/applications/Tangential_complex/CMakeLists.txt create mode 100644 Tangential_complex/applications/Tangential_complex/euler_charact.cpp diff --git a/Tangential_complex/applications/Tangential_complex/CMakeLists.txt b/Tangential_complex/applications/Tangential_complex/CMakeLists.txt new file mode 100644 index 00000000000..0f87ac4302d --- /dev/null +++ b/Tangential_complex/applications/Tangential_complex/CMakeLists.txt @@ -0,0 +1,39 @@ +# Created by the script cgal_create_cmake_script +# This is the CMake script for compiling a CGAL application. + + +project( Tangential_complex_apps ) + +cmake_minimum_required(VERSION 2.6.2) +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) + if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) + cmake_policy(VERSION 2.8.4) + else() + cmake_policy(VERSION 2.6) + endif() +endif() + +find_package(CGAL QUIET COMPONENTS Core ) + +if ( CGAL_FOUND ) + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + include_directories (BEFORE "../../include") + + include( CGAL_CreateSingleSourceCGALProgram ) + + create_single_source_cgal_program( "euler_charact.cpp" ) + + else() + message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") + endif() + +else() + + message(STATUS "This program requires the CGAL library, and will not be compiled.") + +endif() + diff --git a/Tangential_complex/applications/Tangential_complex/euler_charact.cpp b/Tangential_complex/applications/Tangential_complex/euler_charact.cpp new file mode 100644 index 00000000000..01e0e1b9970 --- /dev/null +++ b/Tangential_complex/applications/Tangential_complex/euler_charact.cpp @@ -0,0 +1,19 @@ +#include + +using namespace CGAL::Tangential_complex_; + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + std::cout << "Usage: euler_charact \n"; + return 0; + } + + Simplicial_complex complex; + complex.load_simplices_from_OFF(argv[1]); + + complex.euler_characteristic(true); + + return 0; +} From a53c2f83b65975d13acb42342d91eef8608ff593 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Feb 2016 15:02:20 +0100 Subject: [PATCH 407/487] add_simplex now tells if the simplex was actually inserted + empty() function + is_pure_pseudomanifold now optionally handles borders --- .../Tangential_complex/Simplicial_complex.h | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index bda063aa1d9..b1cacf241c1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -51,7 +51,8 @@ public: // If perform_checks = true, the function: // - won't insert the simplex if it is already in a higher dim simplex // - will erase any lower-dim simplices that are faces of the new simplex - void add_simplex( + // Returns true if the simplex was added + bool add_simplex( const std::set &s, bool perform_checks = true) { if (perform_checks) @@ -71,7 +72,7 @@ public: s.begin(), s.end())) { // No need to insert it, then - return; + return false; } // Check if the simplex includes some lower-dim simplices if (it_simplex->size() < num_pts @@ -89,7 +90,7 @@ public: m_complex.erase(*it); } } - m_complex.insert(s); + return m_complex.insert(s).second; } // Ignore the point coordinates @@ -138,6 +139,11 @@ public: return m_complex; } + bool empty() + { + return m_complex.empty(); + } + void clear() { m_complex.clear(); @@ -285,6 +291,7 @@ public: // verbose_level = 0, 1 or 2 bool is_pure_pseudomanifold__do_not_check_if_stars_are_connected( int simplex_dim, + bool allow_borders = false, bool exit_at_the_first_problem = false, int verbose_level = 0, std::size_t *p_num_wrong_dim_simplices = NULL, @@ -331,7 +338,8 @@ public: it_map_elt != it_map_end ; ++it_map_elt) { - if (it_map_elt->second != 2) + if (it_map_elt->second != 2 + && (!allow_borders || it_map_elt->second != 1)) { if (verbose_level >= 2) std::cerr << "Found a k-1-face with " @@ -424,6 +432,7 @@ public: bool is_pure_pseudomanifold( int simplex_dim, std::size_t num_vertices, + bool allow_borders = false, bool exit_at_the_first_problem = false, int verbose_level = 0, std::size_t *p_num_wrong_dim_simplices = NULL, @@ -440,6 +449,7 @@ public: *p_num_unconnected_stars = 0; return is_pure_pseudomanifold__do_not_check_if_stars_are_connected( simplex_dim, + allow_borders, exit_at_the_first_problem, verbose_level, p_num_wrong_dim_simplices, @@ -536,7 +546,8 @@ public: boost::add_edge(km1_gv, *kface_it, adj_graph); } - if (dm1_to_d_it->second.size() != 2) + if (dm1_to_d_it->second.size() != 2 + && (!allow_borders || dm1_to_d_it->second.size() != 1)) { ++num_wrong_number_of_cofaces; if (p_wrong_number_of_cofaces_simplices) From 2f099f2305ad356a90ec60a664f49e80bf93ac80 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Feb 2016 15:04:13 +0100 Subject: [PATCH 408/487] Move load_points_from_file + add class Orthogonal_projection --- .../CGAL/Tangential_complex/utilities.h | 118 ++++++++++++++++++ .../Tangential_complex/testing_utilities.h | 102 ++------------- 2 files changed, 127 insertions(+), 93 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index ecaf69a734b..6b32e832d3c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -30,6 +30,7 @@ #include #include +#include #include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) @@ -355,6 +356,87 @@ namespace Tangential_complex_ { return add_it; } + template< + typename Kernel, typename Tangent_space_basis, + typename OutputIteratorPoints, typename OutputIteratorTS> + bool load_points_from_file( + const std::string &filename, + OutputIteratorPoints points, + OutputIteratorTS tangent_spaces, + std::size_t only_first_n_points = std::numeric_limits::max()) + { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + + std::ifstream in(filename); + if (!in.is_open()) + { + std::cerr << "Could not open '" << filename << "'" << std::endl; + return false; + } + + bool contains_tangent_spaces = + (filename.substr(filename.size() - 3) == "pwt"); + + Kernel k; + Point p; + int num_ppints; + in >> num_ppints; + + std::size_t i = 0; + while (i < only_first_n_points && in >> p) + { + *points++ = p; + if (contains_tangent_spaces) + { + Tangent_space_basis tsb(i); + for (int d = 0 ; d < 2 ; ++d) // CJTODO : pas toujours "2" + { + Vector v; + in >> v; + tsb.push_back(CGAL::Tangential_complex_::normalize_vector(v, k)); + } + *tangent_spaces++ = tsb; + } + ++i; + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << "'" << filename << "' loaded." << std::endl; +#endif + + return true; + } + + // 1st line: number of points + // Then one point per line + template + std::ostream &export_point_set( + Kernel const& k, + Point_range const& points, + std::ostream & os, + const char *coord_separator = " ") + { + // Kernel functors + typename Kernel::Construct_cartesian_const_iterator_d ccci = + k.construct_cartesian_const_iterator_d_object(); + + os << points.size() << "\n"; + + typename Point_range::const_iterator it_p = points.begin(); + typename Point_range::const_iterator it_p_end = points.end(); + // For each point p + for ( ; it_p != it_p_end ; ++it_p) + { + for (auto it = ccci(*it_p) ; it != ccci(*it_p, 0) ; ++it) // CJTODO: C++11 + os << CGAL::to_double(*it) << coord_separator; + + os << "\n"; + } + + return os; + } + template Basis compute_gram_schmidt_basis(Basis const& input_basis, K const& k) { @@ -371,6 +453,42 @@ namespace Tangential_complex_ { return output_basis; } + // Functor to compute stereographic projection from S^3(sphere_radius) to R^3 + template + class Orthogonal_projection + { + public: + typedef typename K::FT FT; + typedef typename K::Point_d Point; + + // center_of_projection will be sent to infinity by the projection + Orthogonal_projection( + std::array const& selected_coords, K const& k) + : m_selected_coords(selected_coords), m_k(k) + {} + + Point operator()(Point const& p) const + { + typedef K::FT FT; + typedef K::Point_d Point; + + typename K::Construct_point_d constr_pt = m_k.construct_point_d_object(); + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); + + std::vector projected_p; + projected_p.reserve(3); + + for (int i = 0 ; i < 3 ; ++i) + projected_p.push_back(coord(p, m_selected_coords[i])); + + return constr_pt(3, projected_p.begin(), projected_p.end()); + } + + private: + std::array m_selected_coords; // CJTODO C++11 + K const& m_k; + }; + // Functor to compute radial projection from R^4 to S^3(sphere_radius) // The returned point coordinates are expressed with the origin // at `center_of_sphere`, i.e. the new points are all on the sphere diff --git a/Tangential_complex/test/Tangential_complex/testing_utilities.h b/Tangential_complex/test/Tangential_complex/testing_utilities.h index 1c70713f7d8..36bc179c3a6 100644 --- a/Tangential_complex/test/Tangential_complex/testing_utilities.h +++ b/Tangential_complex/test/Tangential_complex/testing_utilities.h @@ -171,7 +171,7 @@ sparsify_point_set( std::vector dropped_points(input_pts.size(), false); - // Parse the following points, and add them if they are not too close to + // Parse the input points, and add them if they are not too close to // the other points std::size_t pt_idx = 0; for (typename Point_container::const_iterator it_pt = input_pts.begin() ; @@ -185,18 +185,20 @@ sparsify_point_set( INS_range ins_range = points_ds.query_incremental_ANN(*it_pt); - // Drop it if there is another point that: - // - is closer that min_squared_dist - // - and has a higher index + // If another point Q is closer that min_squared_dist, mark Q to be dropped for (INS_iterator nn_it = ins_range.begin() ; nn_it != ins_range.end() ; ++nn_it) { std::size_t neighbor_point_idx = nn_it->first; - typename Kernel::FT sq_dist = nn_it->second; - // The neighbor is too close, we drop the neighbor - if (sq_dist < min_squared_dist) + // If the neighbor is too close, we drop the neighbor + if (nn_it->second < min_squared_dist) + { + // N.B.: If neighbor_point_idx < pt_idx, + // dropped_points[neighbor_point_idx] is already true but adding a + // test doesn't make things faster, so why bother? dropped_points[neighbor_point_idx] = true; + } else break; } @@ -210,92 +212,6 @@ sparsify_point_set( return output; } -template< - typename Kernel, typename OutputIteratorPoints> - bool load_points_from_file( - const std::string &filename, - OutputIteratorPoints points, - std::size_t only_first_n_points = std::numeric_limits::max()) -{ - typedef typename Kernel::Point_d Point; - - std::ifstream in(filename); - if (!in.is_open()) - { - std::cerr << "Could not open '" << filename << "'" << std::endl; - return false; - } - - Point p; - int num_ppints; - in >> num_ppints; - - std::size_t i = 0; - while (i < only_first_n_points && in >> p) - { - *points++ = p; - ++i; - } - -#ifdef CGAL_TC_VERBOSE - std::cerr << "'" << filename << "' loaded." << std::endl; -#endif - - return true; - } - -template< - typename Kernel, typename Tangent_space_basis, - typename OutputIteratorPoints, typename OutputIteratorTS> -bool load_points_from_file( - const std::string &filename, - OutputIteratorPoints points, - OutputIteratorTS tangent_spaces, - std::size_t only_first_n_points = std::numeric_limits::max()) -{ - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Vector_d Vector; - - std::ifstream in(filename); - if (!in.is_open()) - { - std::cerr << "Could not open '" << filename << "'" << std::endl; - return false; - } - - bool contains_tangent_spaces = - (filename.substr(filename.size() - 3) == "pwt"); - - Kernel k; - Point p; - int num_ppints; - in >> num_ppints; - - std::size_t i = 0; - while(i < only_first_n_points && in >> p) - { - *points++ = p; - if (contains_tangent_spaces) - { - Tangent_space_basis tsb(i); - for (int d = 0 ; d < 2 ; ++d) // CJTODO : pas toujours "2" - { - Vector v; - in >> v; - tsb.push_back(CGAL::Tangential_complex_::normalize_vector(v, k)); - } - *tangent_spaces++ = tsb; - } - ++i; - } - -#ifdef CGAL_TC_VERBOSE - std::cerr << "'" << filename << "' loaded." << std::endl; -#endif - - return true; -} - template std::vector generate_points_on_plane( std::size_t num_points, int intrinsic_dim, int ambient_dim) From 17a81c31248c3e66a167bc8dd3c120449b9abef8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Feb 2016 15:12:49 +0100 Subject: [PATCH 409/487] export_TC can now give the list of inconsistent simplices + ... + Add export_point_set + Allow to export the sparsified point set + Better OFF output (no more duplicated triangles) + Clean-up --- .../Tangential_complex/benchmark_tc.cpp | 115 ++++++++------- .../include/CGAL/Tangential_complex.h | 131 ++++++++++++------ 2 files changed, 149 insertions(+), 97 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 422a7d9ce26..28285a2c728 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -6,6 +6,19 @@ # define TBB_USE_THREADING_TOOL #endif +#include + +//#define CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +//#define TC_PROTECT_POINT_SET_DELTA 0.003 +//#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test +//#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY +//#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points +//#define TC_NO_EXPORT +//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 0.95 // 1.9 - 0.95 +#define CGAL_TC_EXPORT_SPARSIFIED_POINT_SET + +const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 500000; // 1e10 + #include #include #include @@ -41,13 +54,6 @@ typedef CGAL::Tangential_complex< Kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag> TC; -//#define CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM -//#define TC_PROTECT_POINT_SET_DELTA 0.003 -//#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test -//#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY -//#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points -//#define TC_NO_EXPORT - #ifdef TC_PROTECT_POINT_SET_DELTA # include // CJTODO TEST @@ -57,6 +63,8 @@ typedef CGAL::Tangential_complex< std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); #endif +using namespace CGAL::Tangential_complex_; + class XML_perf_data { public: @@ -167,6 +175,7 @@ private: int m_max_allowed_dim; }; +// color_inconsistencies: only works if p_complex = NULL template bool export_to_off( TC const& tc, @@ -186,12 +195,15 @@ bool export_to_off( Kernel k; FT center_pt[] = { -0.5, -CGAL::sqrt(3.) / 2, -0.5, CGAL::sqrt(3.) / 2 }; FT proj_pt[] = { 0., 0., 0., 0.2 }; - CGAL::Tangential_complex_::S3_to_R3_stereographic_projection + S3_to_R3_stereographic_projection proj_functor(0.2, Point(4, ¢er_pt[0], ¢er_pt[4]), k); #else CGAL::Identity proj_functor; + //Kernel k; + //std::array sel = { 1, 3, 5 }; + //Orthogonal_projection proj_functor(sel, k); #endif if (tc.intrinsic_dimension() <= 3) @@ -320,6 +332,11 @@ void make_tc(std::vector &points, points = sparsify_point_set(k, points, sparsity*sparsity); std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << "\n"; + +#ifdef CGAL_TC_EXPORT_SPARSIFIED_POINT_SET + std::ofstream ps_stream("output/sparsified_point_set.txt"); + export_point_set(k, points, ps_stream); +#endif } #ifdef TC_PROTECT_POINT_SET_DELTA @@ -367,41 +384,6 @@ void make_tc(std::vector &points, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - //=========================================================================== - // CJTODO TEMP - //=========================================================================== - /*{ - TC::Simplicial_complex complex; - int max_dim = tc.export_TC(complex, false); - complex.display_stats(); - - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_ALPHA_COMPLEX.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(complex, off_stream); - - // Collapse - complex.collapse(max_dim); - { - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_AFTER_COLLAPSE.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(complex, off_stream); - } - std::size_t num_wrong_dim_simplices, - num_wrong_number_of_cofaces, - num_unconnected_stars; - bool pure_manifold = complex.is_pure_pseudomanifold( - intrinsic_dim, tc.number_of_vertices(), false, 1, - &num_wrong_dim_simplices, &num_wrong_number_of_cofaces, - &num_unconnected_stars); - complex.display_stats(); - } - return;*/ - // CJTODO TEMP =========================== - #ifdef CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY if (ambient_dim <= 4) tc.check_if_all_simplices_are_in_the_ambient_delaunay(); @@ -412,9 +394,17 @@ void make_tc(std::vector &points, //=========================================================================== // Export to OFF //=========================================================================== + + // Create complex + int max_dim = -1; + TC::Simplicial_complex complex; + std::set > inconsistent_simplices; + max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices); + t.reset(); double export_before_time = - (export_to_off(tc, input_name_stripped, "_INITIAL_TC") ? t.elapsed() : -1); + (export_to_off(tc, input_name_stripped, "_INITIAL_TC", true, + &complex, &inconsistent_simplices) ? t.elapsed() : -1); t.reset(); unsigned int num_perturb_steps = 0; @@ -458,8 +448,15 @@ void make_tc(std::vector &points, //========================================================================= // Export to OFF //========================================================================= + + // Re-build the complex + std::set > inconsistent_simplices; + max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices); + t.reset(); - bool exported = export_to_off(tc, input_name_stripped, "_AFTER_FIX", true); + bool exported = export_to_off( + tc, input_name_stripped, "_AFTER_FIX", true, &complex, + &inconsistent_simplices); double export_after_perturb_time = (exported ? t.elapsed() : -1); t.reset(); @@ -477,10 +474,8 @@ void make_tc(std::vector &points, // CJTODO TEST //tc.check_and_solve_inconsistencies_by_filtering_simplices_out(); - int max_dim = -1; double fix2_time = -1; double export_after_fix2_time = -1.; - TC::Simplicial_complex complex; if (add_high_dim_simpl) { //========================================================================= @@ -494,7 +489,7 @@ void make_tc(std::vector &points, tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); #endif fix2_time = t.elapsed(); t.reset(); - max_dim = tc.export_TC(complex, false); + /*std::set > not_delaunay_simplices; if (ambient_dim <= 4) { @@ -505,15 +500,22 @@ void make_tc(std::vector &points, //========================================================================= // Export to OFF //========================================================================= + + // Re-build the complex + std::set > inconsistent_simplices; + max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices); + t.reset(); bool exported = export_to_off( - tc, input_name_stripped, "_AFTER_FIX2", false, &complex); + tc, input_name_stripped, "_AFTER_FIX2", false, &complex, + &inconsistent_simplices); double export_after_fix2_time = (exported ? t.elapsed() : -1); t.reset(); } else { - max_dim = tc.export_TC(complex, false); + std::set > inconsistent_simplices; + max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices); } complex.display_stats(); @@ -528,7 +530,7 @@ void make_tc(std::vector &points, std::inserter(higher_dim_simplices, higher_dim_simplices.begin())); export_to_off( tc, input_name_stripped, "_BEFORE_COLLAPSE", false, &complex, - &higher_dim_simplices);*/ + &inconsistent_simplices, &higher_dim_simplices);*/ //=========================================================================== // Collapse @@ -549,7 +551,13 @@ void make_tc(std::vector &points, std::set > wrong_number_of_cofaces_simplices; std::set > unconnected_stars_simplices; bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold( - intrinsic_dim, tc.number_of_vertices(), false, 1, + intrinsic_dim, tc.number_of_vertices(), +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + true, // allow borders +#else + false, // do NOT allow borders +#endif + false, 1, &num_wrong_dim_simplices, &num_wrong_number_of_cofaces, &num_unconnected_stars, &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, @@ -810,7 +818,8 @@ int main() { load_points_from_file( input, std::back_inserter(points), - std::back_inserter(tangent_spaces)/*, 600*/); + std::back_inserter(tangent_spaces), + ONLY_LOAD_THE_FIRST_N_POINTS); } #ifdef CGAL_TC_PROFILING diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2ba43a69ea7..3ee12855b3c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -44,7 +44,7 @@ # include -#include // CJTODO TEMP +#include // CJTODO DEBUG? #include #include @@ -79,7 +79,7 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) -//static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP +//static std::ofstream csv_stream("output/stats.csv"); // CJTODO DEBUG //CJTODO: debug //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_2 @@ -87,7 +87,6 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE //#define CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS -//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 1.9 // 0.95 namespace CGAL { @@ -391,6 +390,34 @@ public: void compute_tangential_complex() { + // CJTODO TEMP + /*{ + INS_range ins_range = m_points_ds.query_incremental_ANN( + m_k.construct_point_d_object()(8, ORIGIN)); + int c = 0; + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() && c < 10 ; + ++nn_it, ++c) + { + std::size_t neighbor_point_idx = nn_it->first; + FT sqdist = nn_it->second; + std::cerr << neighbor_point_idx << ":" << CGAL::sqrt(sqdist) << "\n"; + } + } + { + INS_range ins_range = m_points_ds.query_incremental_ANN( + m_points[234]); + int c = 0; + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() && c < 10 ; + ++nn_it, ++c) + { + std::size_t neighbor_point_idx = nn_it->first; + FT sqdist = nn_it->second; + std::cerr << neighbor_point_idx << ":" << CGAL::sqrt(sqdist) << "\n"; + } + }*/ + #ifdef CGAL_TC_PERFORM_EXTRA_CHECKS std::cerr << red << "WARNING: CGAL_TC_PERFORM_EXTRA_CHECKS is defined. " << "Computation might be slower than usual.\n" << white; @@ -805,6 +832,7 @@ public: num_simplices, num_inconsistent_simplices, num_inconsistent_stars); } + // First clears the complex then exports the TC into it // Return the max dimension of the simplices // check_lower_and_higher_dim_simplices : 0 (false), 1 (true), 2 (auto) // If the check is enabled, the function: @@ -815,7 +843,8 @@ public: // N.B.: The check is quite expensive. int export_TC(Simplicial_complex &complex, bool export_infinite_simplices = false, - int check_lower_and_higher_dim_simplices = 2) const + int check_lower_and_higher_dim_simplices = 2, + std::set *p_inconsistent_simplices = NULL) const { #if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) std::cerr << yellow @@ -826,6 +855,7 @@ public: #endif int max_dim = -1; + complex.clear(); // For each triangulation for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) @@ -863,7 +893,15 @@ public: continue; #endif - complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1); + // Try to insert the simplex + bool added = + complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1); + + // Inconsistent? + if (p_inconsistent_simplices && added && !is_simplex_consistent(c)) + { + p_inconsistent_simplices->insert(c); + } } } @@ -995,7 +1033,7 @@ private: } else { - std::cerr << "***************** Intersection is not a point ********************\n"; // CJTODO TEMP + std::cerr << "***************** Intersection is not a point ********************\n"; // CJTODO DEBUG // Compute the intersection between Voronoi_cell(s) and Tq // We need Q, i.e. the vertices which are common neighbors of all // vertices of full_simplex in the Delaunay triangulation, but we @@ -1049,7 +1087,7 @@ private: pqueues[simplex_dim - m_intrinsic_dim].push( Simplex_and_alpha(p, is, squared_alpha, thickening_v)); - // CJTODO TEMP + // CJTODO DEBUG /*std::cerr << "Just inserted the simplex "; std::copy(full_simplex.begin(), full_simplex.end(), @@ -1152,7 +1190,7 @@ public: FT(0), /* sqlen_threshold: default value */ true /* add_to_thickening_vectors */); - // CJTODO TEMP + // CJTODO DEBUG if (!vec_added) { std::cerr << "FYI: the thickening vector was not added " @@ -1194,7 +1232,7 @@ public: Indexed_simplex full_s = saa.m_simplex; full_s.insert(saa.m_center_point_index); - // CJTODO TEMP + // CJTODO DEBUG bool is_this_simplex_somewhere = false; for(auto ii : saa.m_simplex) // CJTODO C++11 { @@ -1210,7 +1248,7 @@ public: if (!is_this_simplex_somewhere) std::cerr << "WOW The simplex is NOWHERE!\n"; - // CJTODO TEMP + // CJTODO DEBUG if (m_ambient_dim <= 3) { if (is_simplex_in_the_ambient_delaunay(full_s)) @@ -1254,7 +1292,7 @@ public: << num_inconsistent_simplices << "\n"; #endif } - // CJTODO TEMP + // CJTODO DEBUG else { std::cerr << "SUCCESS: " @@ -2013,7 +2051,6 @@ private: else { update_star__with_thickening_vector(i); - //check_if_all_simplices_are_in_the_ambient_delaunay(); // CJTODO TEMP } #else update_star__no_thickening_vectors(i); @@ -3380,6 +3417,30 @@ next_face: return is_inconsistent; } + // 1st line: number of points + // Then one point per line + std::ostream &export_point_set( + std::ostream & os, + bool use_perturbed_points = false, + const char *coord_separator = " ") const + { + if (use_perturbed_points) + { + std::vector perturbed_points; + perturbed_points.reserve(m_points.size()); + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + perturbed_points.push_back(compute_perturbed_point(i)); + + return export_point_set( + m_k, perturbed_points, os, coord_separator); + } + else + { + return export_point_set( + m_k, m_points, os, coord_separator); + } + } + template > std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices, @@ -3414,22 +3475,22 @@ next_face: use_perturbed_points ? compute_perturbed_point(i) : *it_p); for (int ii = 0 ; ii < N ; ++ii) { - int i = 0; + int j = 0; #if CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS // For flat torus os << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 2)) << " " << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 3)) << " " << 1 * CGAL::to_double(coord(p, 1)); #else - for ( ; i < num_coords ; ++i) - os << CGAL::to_double(coord(p, i)) << " "; + for ( ; j < num_coords ; ++j) + os << CGAL::to_double(coord(p, j)) << " "; #endif - if (i == 2) + if (j == 2) os << "0"; #ifdef CGAL_TC_EXPORT_NORMALS - for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double(coord(*it_os->begin(), i)); + for (j = 0 ; j < num_coords ; ++j) + os << " " << CGAL::to_double(coord(*it_os->begin(), j)); #endif os << "\n"; } @@ -3564,7 +3625,7 @@ next_face: unproject_point(Cq, m_tangent_spaces[q_idx], q_tr_traits), circumsphere_sqradius_q); - // CJTODO TEMP ==================== + // CJTODO DEBUG ==================== /*{ INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(global_Cp)); for (INS_iterator nn_it = ins_range.begin() ; @@ -3573,8 +3634,6 @@ next_face: { FT neighbor_sqdist = nn_it->second; - //std::cerr << nn_it->first << " : " << neighbor_sqdist << " / "; // CJTODO TEMP - // When we're sure we got all the potential points, break //if (neighbor_sqdist > circumsphere_sqradius_p + m_sq_half_sparsity) // break; @@ -3582,7 +3641,6 @@ next_face: std::size_t neighbor_point_idx = nn_it->first; FT point_to_Cp_power_sqdist = k_power_dist( global_Cp, compute_perturbed_weighted_point(neighbor_point_idx)); - //std::cerr << point_to_Cp_power_sqdist << "\n"; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_Cp_power_sqdist <= FT(0) && inconsistent_simplex.find(neighbor_point_idx) == @@ -3630,24 +3688,12 @@ next_face: auto sid = (o == NEGATIVE ? side(simplex_pts_in_Tq.rbegin(), simplex_pts_in_Tq.rend(), p) : side(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end(), p)); - switch(sid) - { - case ON_NEGATIVE_SIDE: - std::cerr << "ON_NEGATIVE_SIDE\n"; // CJTODO TEMP - break; - case ON_POSITIVE_SIDE: - std::cerr << "ON_POSITIVE_SIDE\n"; // CJTODO TEMP - break; - case ON_ORIENTED_BOUNDARY: - std::cerr << "ON_ORIENTED_BOUNDARY\n"; // CJTODO TEMP - break; - } }*/ } CGAL_assertion_msg(!inside_pt_indices.empty(), "There should be at least one vertex inside the sphere"); - // CJTODO TEMP DEBUG + // CJTODO DEBUG /*if (inside_pt_indices.empty()) { //compute_tangent_triangulation(q_idx, true); @@ -3663,7 +3709,7 @@ next_face: std::cerr << "\n"; }*/ - // CJTODO TEMP DEBUG + // CJTODO DEBUG // If co-intrinsic dimension = 1, let's compare normals /*if (m_ambient_dim - m_intrinsic_dim == 1) { @@ -3683,7 +3729,7 @@ next_face: csv_stream << "\n"; }*/ - // CJTODO TEMP DEBUG + // CJTODO DEBUG if (inside_pt_indices.size() > 1) { std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " @@ -3754,7 +3800,7 @@ next_face: } } - // CJTODO TEMP ==================== + // CJTODO DEBUG ==================== /*{ typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); typename K::Point_weight_d k_weight = m_k.point_weight_d_object(); @@ -3768,8 +3814,6 @@ next_face: { FT neighbor_sqdist = nn_it->second; - //std::cerr << nn_it->first << " : " << neighbor_sqdist << " / "; // CJTODO TEMP - // When we're sure we got all the potential points, break if (neighbor_sqdist > k_weight(C) + m_sq_half_sparsity) break; @@ -3777,7 +3821,6 @@ next_face: std::size_t neighbor_point_idx = nn_it->first; FT point_to_C_power_sqdist = k_power_dist(C, compute_perturbed_weighted_point(neighbor_point_idx)); - //std::cerr << point_to_Cp_power_sqdist << "\n"; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_C_power_sqdist <= FT(-0.000001) && inconsistent_simplex.find(neighbor_point_idx) == @@ -3848,7 +3891,7 @@ next_face: inconsistencies_found = true; break; } - // CJTODO TEMP + // CJTODO DEBUG /*else if (m_ambient_dim - m_intrinsic_dim == 1) { typename K::Difference_of_points_d k_diff_pts = @@ -4561,8 +4604,8 @@ public: // Return a pair void check_correlation_between_inconsistencies_and_fatness() const { - std::ofstream csv_consistent("output/correlation_consistent.csv"); // CJTODO TEMP - std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO TEMP + std::ofstream csv_consistent("output/correlation_consistent.csv"); // CJTODO DEBUG + std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO DEBUG if (m_intrinsic_dim < 3) { std::cerr From 26a8b93870c7a664de0a3f539585a8aafb1586a8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Feb 2016 19:53:01 +0100 Subject: [PATCH 410/487] Add CGAL_TC_EXPORT_ALL_COORDS_IN_OFF macro --- .../Tangential_complex/benchmark_tc.cpp | 3 ++- .../include/CGAL/Tangential_complex.h | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 28285a2c728..cabb38fc335 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -15,7 +15,8 @@ //#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points //#define TC_NO_EXPORT //#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 0.95 // 1.9 - 0.95 -#define CGAL_TC_EXPORT_SPARSIFIED_POINT_SET +//#define CGAL_TC_EXPORT_SPARSIFIED_POINT_SET +//#define CGAL_TC_EXPORT_ALL_COORDS_IN_OFF const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 500000; // 1e10 diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3ee12855b3c..cd81510902e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -2669,6 +2669,7 @@ next_face: } // Project the point in the tangent space + // Resulting point coords are expressed in tsb's space Tr_bare_point project_point(const Point &p, const Tangent_space_basis &tsb) const { @@ -2703,6 +2704,7 @@ next_face: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p + // Resulting point coords are expressed in tsb's space Tr_point project_point_and_compute_weight(const Weighted_point &wp, const Tangent_space_basis &tsb, const Tr_traits &tr_traits) const @@ -2715,11 +2717,15 @@ next_face: k_drop_w(wp), k_point_weight(wp), tsb, tr_traits); } + // Same as above, with slightly different parameters Tr_point project_point_and_compute_weight(const Point &p, const FT w, const Tangent_space_basis &tsb, const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); + + typename K::Construct_point_d constr_pt = + m_k.construct_point_d_object(); typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); typename K::Difference_of_points_d diff_points = @@ -2739,7 +2745,7 @@ next_face: // Ambiant-space coords of the projected point std::vector p_proj(ccci(origin), ccci(origin, 0)); coords.reserve(tsb.dimension()); - for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) + for (std::size_t i = 0 ; i < tsb.dimension() ; ++i) { // Local coords are given by the scalar product with the vectors of tsb FT c = scalar_pdct(v, tsb[i]); @@ -2769,14 +2775,13 @@ next_face: FT sq_dist_to_proj_pt = 0; if (!same_dim) { - Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); + Point projected_pt = constr_pt(point_dim, p_proj.begin(), p_proj.end()); sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt); } return tr_traits.construct_weighted_point_d_object() ( - tr_traits.construct_point_d_object()( - static_cast(coords.size()), coords.begin(), coords.end()), + constr_pt(static_cast(coords.size()), coords.begin(), coords.end()), w - sq_dist_to_proj_pt ); } @@ -3462,7 +3467,12 @@ next_face: typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); +#ifdef CGAL_TC_EXPORT_ALL_COORDS_IN_OFF + int num_coords = m_ambient_dim; +#else int num_coords = min(m_ambient_dim, 3); +#endif + #ifdef CGAL_TC_EXPORT_NORMALS OS_container::const_iterator it_os = m_orth_spaces.begin(); #endif From 233bfc4f4d5f04a585c1c2e7f23cd8e966c7b7ab Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Feb 2016 19:54:09 +0100 Subject: [PATCH 411/487] Fix usage of load_points_from_file --- .../Tangential_complex/benchmark_mesh_d.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp index 0338d46ffeb..1471adbf990 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -6,6 +6,9 @@ # define TBB_USE_THREADING_TOOL #endif +#include + +const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 100000000; #include #include @@ -160,7 +163,7 @@ void make_mesh( std::set > wrong_number_of_cofaces_simplices; std::set > unconnected_stars_simplices; bool is_pure_pseudomanifold = mesh.complex().is_pure_pseudomanifold( - intrinsic_dim, mesh.number_of_vertices(), false, 1, + intrinsic_dim, mesh.number_of_vertices(), false, false, 1, &num_wrong_dim_simplices, &num_wrong_number_of_cofaces, &num_unconnected_stars, &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, @@ -302,6 +305,7 @@ int main() #endif std::vector points; + Mesh::TS_container tangent_spaces; if (input == "generate_moment_curve") { @@ -373,8 +377,10 @@ int main() } else { - load_points_from_file( - input, std::back_inserter(points)/*, 600*/); + load_points_from_file( + input, std::back_inserter(points), + std::back_inserter(tangent_spaces), + ONLY_LOAD_THE_FIRST_N_POINTS); } #ifdef CGAL_MESH_D_PROFILING From 7756c3ae9afdc89376c4f06bfc489981d2aeaec1 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 22 Feb 2016 16:14:14 +0100 Subject: [PATCH 412/487] Faster intersection computation --- .../Tangential_complex/benchmark_mesh_d.cpp | 11 +- Tangential_complex/include/CGAL/Mesh_d.h | 185 ++++++++++++++---- 2 files changed, 154 insertions(+), 42 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp index 1471adbf990..ce01f749e6e 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -38,13 +38,13 @@ const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt"; typedef CGAL::Epick_d Kernel; typedef Kernel::FT FT; typedef Kernel::Point_d Point; -typedef CGAL::Mesh_d< - Kernel, CGAL::Dynamic_dimension_tag, - CGAL::Parallel_tag> Mesh; +typedef CGAL::Mesh_d Mesh; //#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY //#define MESH_D_INPUT_STRIDES 10 // only take one point every MESH_D_INPUT_STRIDES points //#define MESH_D_NO_EXPORT +//#define CGAL_MESH_D_USE_LINEAR_PROG_TO_COMPUTE_INTERSECTION +//#define CGAL_MESH_D_FILTER_BY_TESTING_ALL_VERTICES_TANGENT_PLANES template @@ -90,6 +90,7 @@ void make_mesh( const char *input_name = "mesh") { Kernel k; + Kernel lk; // local kernel (intrinsic dim) //=========================================================================== // Init @@ -131,9 +132,9 @@ void make_mesh( #ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, - points_not_sparse.begin(), points_not_sparse.end(), k); + points_not_sparse.begin(), points_not_sparse.end(), k, lk); #else - Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, k); + Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, k, lk); #endif double init_time = t.elapsed(); t.reset(); diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h index 3d72ea2e4d5..c935f376355 100644 --- a/Tangential_complex/include/CGAL/Mesh_d.h +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -80,7 +80,7 @@ private: /// The class Mesh_d represents a d-dimensional mesh template < typename Kernel_, // ambiant kernel - typename DimensionTag, // intrinsic dimension + typename Local_kernel_, // local kernel (intrinsic dimension) typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Delaunay_triangulation < @@ -98,17 +98,19 @@ class Mesh_d typedef Kernel_ K; typedef typename K::FT FT; typedef typename K::Point_d Point; + typedef typename K::Weighted_point_d Weighted_point; typedef typename K::Vector_d Vector; + typedef Local_kernel_ LK; + typedef typename LK::Point_d Local_point; + typedef typename LK::Weighted_point_d Local_weighted_point; + typedef Tr Triangulation; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename Triangulation::Finite_full_cell_const_iterator Tr_finite_full_cell_const_iterator; - typedef Basis Tangent_space_basis; - typedef Basis Orthogonal_space_basis; - typedef std::vector Points; typedef Point_cloud_data_structure Points_ds; @@ -121,8 +123,11 @@ class Mesh_d typedef std::set Indexed_simplex; public: + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; typedef std::vector TS_container; typedef std::vector OS_container; + private: // For transform_iterator @@ -163,9 +168,11 @@ public: #ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM InputIterator first_for_tse, InputIterator last_for_tse, #endif - const K &k = K() + const K &k = K(), + const LK &lk = LK() ) : m_k(k) + , m_lk(lk) , m_intrinsic_dim(intrinsic_dimension) , m_half_sparsity(0.5*sparsity) , m_sq_half_sparsity(m_half_sparsity*m_half_sparsity) @@ -287,7 +294,7 @@ public: } }*/ - Get_functor::type sum_vecs(m_k); + Get_functor::type sum_vecs(m_k); // Extract complex // CJTODO: parallelize @@ -311,7 +318,7 @@ public: bool keep_it = false; bool is_uncertain = false; -#ifdef MESH_D_FILTER_BY_TESTING_ALL_VERTICES_TANGENT_PLANES +#ifdef CGAL_MESH_D_FILTER_BY_TESTING_ALL_VERTICES_TANGENT_PLANES int num_intersections = 0; for (auto vh : kf) // CJTODO C++11 { @@ -331,34 +338,30 @@ public: } #else // Compute the intersection with all tangent planes of the vertices - // of the k-face + // of the k-face then compute a weighted barycenter FT sum_weights = 0; Vector weighted_sum_of_inters = m_k.construct_vector_d_object()(m_ambient_dim); for (auto vh : kf) // CJTODO C++11 { - boost::optional intersection = + Point intersection = compute_aff_of_voronoi_face_and_tangent_subspace_intersection( boost::adaptors::transform(kf, vertex_handle_to_point), +#ifdef CGAL_MESH_D_USE_LINEAR_PROG_TO_COMPUTE_INTERSECTION m_orth_spaces[vh->data()]); +#else + m_tangent_spaces[vh->data()]); +#endif - if (intersection) - { - FT weight = - FT(1) / m_k.squared_distance_d_object()(vh->point(), *intersection); - sum_weights += weight; - weighted_sum_of_inters = sum_vecs( - weighted_sum_of_inters, - m_k.scaled_vector_d_object()( - m_k.point_to_vector_d_object()(*intersection), weight)); - } - else - { - // CJTODO TEMP DEBUG - std::cerr << std::hex << (unsigned int)&k_face << std::dec - << red << "No intersection" << white << "\n"; - } + FT weight = + FT(1) / m_k.squared_distance_d_object()(vh->point(), intersection); + sum_weights += weight; + weighted_sum_of_inters = sum_vecs( + weighted_sum_of_inters, + m_k.scaled_vector_d_object()( + m_k.point_to_vector_d_object()(intersection), weight)); } + if (sum_weights > 0) { // Compute the weighted barycenter @@ -674,6 +677,85 @@ private: return common_neighbors; } + Point unproject_point(const Local_point &lp, + const Tangent_space_basis &tsb) const + { + typename K::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename K::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename LK::Compute_coordinate_d coord = + m_lk.compute_coordinate_d_object(); + + Point global_point = m_points[tsb.origin()]; + for (int i = 0 ; i < m_intrinsic_dim ; ++i) + { + global_point = k_transl( + global_point, k_scaled_vec(tsb[i], coord(lp, i))); + } + + return global_point; + } + + // Project the point in the tangent space + // The weight will be the squared distance between p and the projection of p + // Resulting point coords are expressed in tsb's space + Local_weighted_point project_point_and_compute_weight( + const Point &p, const FT w, const Tangent_space_basis &tsb) const + { + const int point_dim = m_k.point_dimension_d_object()(p); + + typename K::Construct_point_d constr_pt = + m_k.construct_point_d_object(); + typename K::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename K::Difference_of_points_d diff_points = + m_k.difference_of_points_d_object(); + typename K::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename K::Construct_cartesian_const_iterator_d ccci = + m_k.construct_cartesian_const_iterator_d_object(); + + typename LK::Construct_point_d local_constr_pt = + m_lk.construct_point_d_object(); + + Point const& origin = m_points[tsb.origin()]; + Vector v = diff_points(p, origin); + + // Same dimension? Then the weight is 0 + bool same_dim = (point_dim == tsb.dimension()); + + std::vector coords; + // Ambiant-space coords of the projected point + std::vector p_proj(ccci(origin), ccci(origin, 0)); + coords.reserve(tsb.dimension()); + for (std::size_t i = 0 ; i < tsb.dimension() ; ++i) + { + // Local coords are given by the scalar product with the vectors of tsb + FT c = scalar_pdct(v, tsb[i]); + coords.push_back(c); + + // p_proj += c * tsb[i] + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += c * coord(tsb[i], j); + } + + // Same dimension? Then the weight is 0 + FT sq_dist_to_proj_pt = 0; + if (!same_dim) + { + Point projected_pt = constr_pt(point_dim, p_proj.begin(), p_proj.end()); + sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt); + } + + return m_lk.construct_weighted_point_d_object() + ( + local_constr_pt( + static_cast(coords.size()), coords.begin(), coords.end()), + w - sq_dist_to_proj_pt + ); + } + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P // Note that the computation is made in global coordinates. @@ -688,12 +770,9 @@ private: // Fv: Voronoi k-face // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) - typename Kernel::Scalar_product_d scalar_pdct = - m_k.scalar_product_d_object(); - typename Kernel::Point_to_vector_d pt_to_vec = - m_k.point_to_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = - m_k.compute_coordinate_d_object(); + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); + typename K::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); std::size_t card_P = P.size(); std::size_t card_Q = Q.size(); @@ -829,22 +908,53 @@ private: return ret; } +#ifdef CGAL_MESH_D_USE_LINEAR_PROG_TO_COMPUTE_INTERSECTION + // CJTODO TEMP: this is the old slow code => remove this macro + // Returns any point of the intersection between aff(voronoi_cell) and a // tangent space. // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Return value: the point coordinates are expressed in the tsb base template - boost::optional - compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + Point + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( Point_range_a const& P, Orthogonal_space_basis const& orthogonal_subspace_basis) const { - // As we're only interested by aff(v), Q is empty - return compute_voronoi_face_and_tangent_subspace_intersection( - P, std::vector(), - orthogonal_subspace_basis); + // As we're only interested by aff(v), Q is empty + return *compute_voronoi_face_and_tangent_subspace_intersection( + P, std::vector(), + orthogonal_subspace_basis); + } + +#else + + // Returns any point of the intersection between aff(voronoi_cell) and a + // tangent space. + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Return value: the point coordinates are expressed in the tsb base + template + Point + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + Point_range const& P, + Tangent_space_basis const& tangent_subspace_basis) const + { + std::vector projected_pts; + for (auto const& p : P) + { + projected_pts.push_back( + project_point_and_compute_weight(p, FT(0), tangent_subspace_basis)); } + Local_weighted_point power_center = + m_lk.power_center_d_object()(projected_pts.begin(), projected_pts.end()); + + return unproject_point( + m_lk.point_drop_weight_d_object()(power_center), tangent_subspace_basis); + } + +#endif + std::map get_k_faces_and_neighbor_vertices(Triangulation const& tr) { typedef std::map K_faces_and_neighbor_vertices; @@ -1159,6 +1269,7 @@ public: private: const K m_k; + const LK m_lk; const int m_intrinsic_dim; const double m_half_sparsity; const double m_sq_half_sparsity; From 6817479015156d30e30230c363da48f2fb7868bb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Mar 2016 16:16:42 +0100 Subject: [PATCH 413/487] Clean-up --- .../CGAL/Tangential_complex/Point_cloud.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 293b61fa520..9543e827a40 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -21,21 +21,15 @@ #ifndef POINT_CLOUD_H #define POINT_CLOUD_H -#include -#include - #include #include #include #include -#include -#include -#include #include -#include -#include +#include +#include #ifdef CGAL_TC_ANN_IS_AVAILABLE # include @@ -188,9 +182,9 @@ template class Point_cloud_adaptator__nanoflann { public: - typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename Point_container_::value_type Point; + typedef K Kernel; + typedef typename Kernel::FT FT; /// The constructor that sets the data set source Point_cloud_adaptator__nanoflann(Point_container_ const& points, Kernel const& k) From 3f6989dcd7322116c7ed7a22835db9ed7555c9b8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Mar 2016 16:17:57 +0100 Subject: [PATCH 414/487] Try to translate the tangent plane to be closer to the surface --- Tangential_complex/include/CGAL/Mesh_d.h | 182 ++++++++++++++++++----- 1 file changed, 147 insertions(+), 35 deletions(-) diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h index c935f376355..868f2fabd54 100644 --- a/Tangential_complex/include/CGAL/Mesh_d.h +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -232,6 +232,15 @@ public: Wall_clock_timer t; #endif + typedef CGAL::Epick_d Orth_K; + typedef typename Orth_K::Point_d Orth_K_point; + typedef typename Orth_K::Vector_d Orth_K_vector; + + int orth_dim = m_ambient_dim - m_intrinsic_dim; + Orth_K orth_k(orth_dim); + + Get_functor::type orth_k_sum_vecs(orth_k); + // Tangent and orthogonal spaces for (std::size_t i = 0; i < m_points.size(); ++i) { @@ -341,7 +350,7 @@ public: // of the k-face then compute a weighted barycenter FT sum_weights = 0; Vector weighted_sum_of_inters = - m_k.construct_vector_d_object()(m_ambient_dim); + orth_k.construct_vector_d_object()(m_ambient_dim); for (auto vh : kf) // CJTODO C++11 { Point intersection = @@ -369,6 +378,67 @@ public: m_k.scaled_vector_d_object()( weighted_sum_of_inters, FT(1) / sum_weights)); + //**************************************************************** + // Translate the tangent plane to be closer to the surface + //**************************************************************** + + // Estimate the normal subspace at point "avg_inters" + Tangent_space_basis tsb; + Orthogonal_space_basis osb; + tsb = compute_tangent_space( + avg_inters, std::numeric_limits::max(), + true/*normalize*/, &osb); + + unsigned int num_points_for_nghb_query = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); + KNS_range kns_range = m_points_ds.query_ANN( + avg_inters, num_points_for_nghb_query, false); + + FT sum_weights_of_barycenter = 0; + Orth_K_vector weighted_sum_of_neighbors = + orth_k.construct_vector_d_object()(orth_dim); + KNS_iterator nn_it = kns_range.begin(); + for (unsigned int j = 0 ; + j < num_points_for_nghb_query && nn_it != kns_range.end() ; + ++j, ++nn_it) + { + Point const& nghb = m_points[nn_it->first]; + + Orth_K_point proj_nghb = project_point(nghb, osb, orth_k, &avg_inters); + + FT weight = + FT(1) / m_k.squared_distance_d_object()(nghb, avg_inters); + sum_weights_of_barycenter += weight; + weighted_sum_of_neighbors = orth_k_sum_vecs( + weighted_sum_of_neighbors, + orth_k.scaled_vector_d_object()( + orth_k.point_to_vector_d_object()(proj_nghb), weight)); + } + + //sum_weights_of_barycenter *= 8; // CJTODO TEMP + + // Compute the weighted barycenter + Point translated_origin = unproject_point( + orth_k.vector_to_point_d_object()( + orth_k.scaled_vector_d_object()( + weighted_sum_of_neighbors, FT(1) / sum_weights_of_barycenter)), + osb, + orth_k, + &avg_inters); + + Point translated_inters = + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + boost::adaptors::transform(kf, vertex_handle_to_point), + tsb, &translated_origin); + + // CJTODO TEMP: exact intersection for the sphere of radius 1 + //translated_inters = orth_k.vector_to_point_d_object()( + // normalize_vector(orth_k.point_to_vector_d_object()(avg_inters), m_k)); + + //**************************************************************** + // Keep the simplex or not? + //**************************************************************** + keep_it = true; // Check if the averaged intersection "i" is inside the Voronoi cell, i.e. // for each common neighbor qi, (i - p0) <= (i - qi) @@ -377,8 +447,8 @@ public: { // If a neighbor is closer than p0 to the average intersection, then // the average intersection is inside another Voronoi cell - if (m_k.squared_distance_d_object()(p0, avg_inters) > - m_k.squared_distance_d_object()(neighbor_vh->point(), avg_inters)) + if (m_k.squared_distance_d_object()(p0, translated_inters) > + m_k.squared_distance_d_object()(neighbor_vh->point(), translated_inters)) { keep_it = false; break; @@ -436,9 +506,10 @@ private: return *s.rbegin() == std::numeric_limits::max(); } + // If i = std::numeric_limits::max(), it is ignored Tangent_space_basis compute_tangent_space( const Point &p - , const std::size_t i + , const std::size_t i = std::numeric_limits::max() , bool normalize_basis = true , Orthogonal_space_basis *p_orth_space_basis = NULL) { @@ -454,7 +525,8 @@ private: Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); ts.push_back(scaled_vec(t, FT(1)/CGAL::sqrt(sqlen(t)))); - m_are_tangent_spaces_computed[i] = true; + if (i != std::numeric_limits::max()) + m_are_tangent_spaces_computed[i] = true; return ts; @@ -476,7 +548,8 @@ private: ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); - m_are_tangent_spaces_computed[i] = true; + if (i != std::numeric_limits::max()) + m_are_tangent_spaces_computed[i] = true; return ts; @@ -493,7 +566,8 @@ private: ts.push_back(t); } - m_are_tangent_spaces_computed[i] = true; + if (i != std::numeric_limits::max()) + m_are_tangent_spaces_computed[i] = true; //return compute_gram_schmidt_basis(ts, m_k); return ts; @@ -551,7 +625,7 @@ private: Eigen::MatrixXd cov = centered.adjoint() * centered; Eigen::SelfAdjointEigenSolver eig(cov); - Tangent_space_basis tsb(i); // p = compute_perturbed_point(i) here + Tangent_space_basis tsb(i); // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues @@ -599,7 +673,8 @@ private: } } - m_are_tangent_spaces_computed[i] = true; + if (i != std::numeric_limits::max()) + m_are_tangent_spaces_computed[i] = true; //************************************************************************* @@ -677,31 +752,66 @@ private: return common_neighbors; } - Point unproject_point(const Local_point &lp, - const Tangent_space_basis &tsb) const + template + Point unproject_point(Projected_point const& lp, + Basis_ const& basis, Projection_space_kernel const& lk, + Point const* origin = NULL) const { typename K::Translated_point_d k_transl = m_k.translated_point_d_object(); typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - typename LK::Compute_coordinate_d coord = - m_lk.compute_coordinate_d_object(); + typename Projection_space_kernel::Compute_coordinate_d coord = + lk.compute_coordinate_d_object(); - Point global_point = m_points[tsb.origin()]; - for (int i = 0 ; i < m_intrinsic_dim ; ++i) + Point global_point = (origin ? *origin : m_points[basis.origin()]); + for (int i = 0 ; i < basis.dimension() ; ++i) { global_point = k_transl( - global_point, k_scaled_vec(tsb[i], coord(lp, i))); + global_point, k_scaled_vec(basis[i], coord(lp, i))); } return global_point; } + // Project the point on a subspace + // Resulting point coords are expressed in basis' space + template + typename Projection_space_kernel::Point_d project_point( + const Point &p, const Basis_ &basis, Projection_space_kernel const& psk, + Point const* origin = NULL) const + { + typename K::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename K::Difference_of_points_d diff_points = + m_k.difference_of_points_d_object(); + + Point const& orig = (origin ? *origin : m_points[basis.origin()]); + Vector v = diff_points(p, orig); + + std::vector coords; + // Ambiant-space coords of the projected point + coords.reserve(basis.dimension()); + for (std::size_t i = 0 ; i < basis.dimension() ; ++i) + { + // Local coords are given by the scalar product with the vectors of basis + FT coord = scalar_pdct(v, basis[i]); + coords.push_back(coord); + } + + return psk.construct_point_d_object()(static_cast( + coords.size()), coords.begin(), coords.end()); + } + // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p // Resulting point coords are expressed in tsb's space - Local_weighted_point project_point_and_compute_weight( - const Point &p, const FT w, const Tangent_space_basis &tsb) const + template + typename Projection_space_kernel::Weighted_point_d + project_point_and_compute_weight( + const Point &p, const FT w, const Basis_ &basis, + Projection_space_kernel const& psk, + Point const* origin = NULL) const { const int point_dim = m_k.point_dimension_d_object()(p); @@ -716,28 +826,28 @@ private: typename K::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); - typename LK::Construct_point_d local_constr_pt = - m_lk.construct_point_d_object(); + typename Projection_space_kernel::Construct_point_d local_constr_pt = + psk.construct_point_d_object(); - Point const& origin = m_points[tsb.origin()]; - Vector v = diff_points(p, origin); + Point const& orig = (origin ? *origin : m_points[basis.origin()]); + Vector v = diff_points(p, orig); // Same dimension? Then the weight is 0 - bool same_dim = (point_dim == tsb.dimension()); + bool same_dim = (point_dim == basis.dimension()); std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(ccci(origin), ccci(origin, 0)); - coords.reserve(tsb.dimension()); - for (std::size_t i = 0 ; i < tsb.dimension() ; ++i) + std::vector p_proj(ccci(orig), ccci(orig, 0)); + coords.reserve(basis.dimension()); + for (std::size_t i = 0 ; i < basis.dimension() ; ++i) { - // Local coords are given by the scalar product with the vectors of tsb - FT c = scalar_pdct(v, tsb[i]); + // Local coords are given by the scalar product with the vectors of basis + FT c = scalar_pdct(v, basis[i]); coords.push_back(c); - // p_proj += c * tsb[i] + // p_proj += c * basis[i] for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += c * coord(tsb[i], j); + p_proj[j] += c * coord(basis[i], j); } // Same dimension? Then the weight is 0 @@ -748,7 +858,7 @@ private: sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt); } - return m_lk.construct_weighted_point_d_object() + return psk.construct_weighted_point_d_object() ( local_constr_pt( static_cast(coords.size()), coords.begin(), coords.end()), @@ -937,20 +1047,22 @@ private: Point compute_aff_of_voronoi_face_and_tangent_subspace_intersection( Point_range const& P, - Tangent_space_basis const& tangent_subspace_basis) const + Tangent_space_basis const& tangent_subspace_basis, + Point const* origin = NULL) const { std::vector projected_pts; for (auto const& p : P) { - projected_pts.push_back( - project_point_and_compute_weight(p, FT(0), tangent_subspace_basis)); + projected_pts.push_back(project_point_and_compute_weight( + p, FT(0), tangent_subspace_basis, m_lk, origin)); } Local_weighted_point power_center = m_lk.power_center_d_object()(projected_pts.begin(), projected_pts.end()); return unproject_point( - m_lk.point_drop_weight_d_object()(power_center), tangent_subspace_basis); + m_lk.point_drop_weight_d_object()(power_center), + tangent_subspace_basis, m_lk, origin); } #endif From fc3034aa64f5bf388dfc9d1da7345851150c0219 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 9 Mar 2016 16:18:28 +0100 Subject: [PATCH 415/487] Refer to the user manual instead of saying everything again --- .../CGAL/Regular_triangulation.h | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index ca3c6786319..b2ff04a315c 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -13,31 +13,8 @@ section in the user manual for what reasonable means. \warning The removal of points is not supported yet. -A regular triangulation is defined as follows. - -Let \f$ {S}^{(w)}\f$ be a set of weighted points in \f$ \mathbb{R}^D\f$. Let -\f$ {p}^{(w)}=(p,w_p), p\in\mathbb{R}^D, w_p\in\mathbb{R}\f$ and -\f$ {z}^{(w)}=(z,w_z), z\in\mathbb{R}^D, w_z\in\mathbb{R}\f$ -be two weighted points. -A weighted point -\f$ {p}^{(w)}=(p,w_p)\f$ can also be seen as a sphere of center \f$ p\f$ and -radius \f$ \sqrt{w_p}\f$. -The power product (or power distance ) -between \f$ {p}^{(w)}\f$ and \f$ {z}^{(w)}\f$ is -defined as -\f[ \Pi({p}^{(w)},{z}^{(w)}) = {\|{p-z}\|^2-w_p-w_z} \f] -where \f$ \|{p-z}\|\f$ is the Euclidean distance between \f$ p\f$ and \f$ z\f$. -\f$ {p}^{(w)}\f$ and \f$ {z}^{(w)}\f$ -are said to be orthogonal if \f$ \Pi{({p}^{(w)}-{z}^{(w)})} -= 0\f$. - -\f$D + 1\f$ weighted points have a unique common orthogonal weighted point -called the power sphere. A sphere \f$ {z}^{(w)}\f$ is said to be -regular if \f$ \forall {p}^{(w)}\in{S}^{(w)}, -\Pi{({p}^{(w)}-{z}^{(w)})}\geq 0\f$. - -A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres -of all simplices are regular. +A comprehensive definition of regular triangulations is available in the +User Manual. Parameters -------------- From 1bfef6846f492a1f42d6eabc15c228eec3de6cfe Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 9 Mar 2016 16:18:56 +0100 Subject: [PATCH 416/487] Typos & small changes --- Triangulation/doc/Triangulation/Triangulation.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index f5a5fbfb4d3..e7e21cf875b 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -58,7 +58,7 @@ entry for more about simplicial complexes. ## What's in this Package? ## -This \cgal package provides three main classes +This \cgal package provides four main classes for creating and manipulating triangulations. The class `CGAL::Triangulation_data_structure` @@ -115,11 +115,10 @@ which \cgal provides one model class: A `TriangulationDataStructure` can represent an abstract pure complex such that any facet is incident to exactly two full cells. -A `TriangulationDataStructure` has a -maximal dimension which is a +A `TriangulationDataStructure` has a maximal dimension which is a positive integer equal to the maximum dimension a full cell can have. This maximal dimension can be chosen by the user at the creation of a -TriangulationDataStructure` and can then be queried using the method `tds.maximal_dimension()`. +`TriangulationDataStructure` and can then be queried using the method `tds.maximal_dimension()`. A `TriangulationDataStructure` also knows the current dimension of its full cells, which can be queried with `tds.current_dimension()`. In the sequel, let us denote the maximal dimension with \f$ D \f$ and the current dimension with \f$ d \f$. @@ -241,7 +240,8 @@ some nested types in `TriangulationDataStructure`. The default values are `CGAL::Triangulation_ds_vertex` and `CGAL::Triangulation_ds_full_cell` -where `TDS` is the current class `Triangulation_data_structure` +where `TDS` is the current class +`Triangulation_data_structure`. This creates a circular dependency, which we resolve in the same way as in the \cgal `Triangulation_2` and `Triangulation_3` packages (see Chapters \ref Chapter_2D_Triangulation_Data_Structure, \ref Chapter_2D_Triangulations, @@ -463,7 +463,7 @@ Let \f$ {S}^{(w)}\f$ be a set of weighted points in \f$ \mathbb{R}^D\f$. Let \f$ {p}^{(w)}=(p,w_p), p\in\mathbb{R}^D, w_p\in\mathbb{R}\f$ and \f$ {z}^{(w)}=(z,w_z), z\in\mathbb{R}^D, w_z\in\mathbb{R}\f$ be two weighted points. -A weighted point +If all weights are positive, a weighted point \f$ {p}^{(w)}=(p,w_p)\f$ can also be seen as a sphere of center \f$ p\f$ and radius \f$ \sqrt{w_p}\f$. The power product (or power distance ) From 1533066077c1a11fa16dd5d5378ee95c6bc18e16 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 10 Mar 2016 19:07:33 +0100 Subject: [PATCH 417/487] Monique's review -- part one --- .../doc/Triangulation/PackageDescription.txt | 2 +- .../doc/Triangulation/Triangulation.txt | 123 +++++++++--------- 2 files changed, 60 insertions(+), 65 deletions(-) diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 312cf68e657..8a343c54ea2 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -94,7 +94,7 @@ The latter two concepts are also abbreviated respectively as `TrVertex` and `TrF ## Triangulation Data Structure ## -- `CGAL::Triangulation_data_structure` +- `CGAL::Triangulation_data_structure` - `CGAL::Triangulation_ds_vertex` - `CGAL::Triangulation_ds_full_cell` - `CGAL::Triangulation_face` diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index e7e21cf875b..24ddb39da14 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -13,7 +13,7 @@ triangulations of points in any dimensions. The `Triangulation_data_structure` handles the combinatorial aspect of triangulations while the geometric classes `Triangulation`, `Delaunay_triangulation` and `Regular_triangulation` allow to -compute and maintain triangulations, Delaunay triangulations and +compute and maintain triangulations, Delaunay triangulations, and regular triangulations of sets of points. \section TriangulationSecIntro Introduction @@ -31,20 +31,39 @@ The sets in \f$ S\f$ (which are subsets of \f$ V\f$) are called singular of which is simplex). A simplex \f$ s\in S\f$ is maximal if it is not a proper subset of some other set in \f$ S\f$. -A simplex having \f$ d+1 \f$ vertices is said of dimension \f$ d \f$. +A simplex having \f$ k+1 \f$ vertices is said of dimension \f$ k \f$. +An \f$ k\f$-face denotes a \f$ k\f$-dimensional simplex, or a simplex with \f$ k+1\f$ +vertices. The simplicial complex is pure if all the maximal simplices have the same dimension. + +A triangulation is a simplicial complex +that is pure, connected and without boundaries nor singularities. The +dimension of the triangulation is the dimension of its maximal +simplices. + In the sequel, we will call these maximal simplices full cells. A face of a simplex is a subset of this simplex. A proper face of a simplex is a strict subset of this simplex. +Two faces \f$ \sigma\f$ and \f$ \sigma'\f$ are incident if and only if +\f$ \sigma'\f$ is a proper face of \f$ \sigma\f$ or vice versa. A complex has no boundaries if any proper face of a simplex is also a proper face of another simplex. -If the vertices are embedded into Euclidean space \f$ \mathbb{R}^d\f$, +If the triangulation is of dimension \f$ d \f$, we use the following terminology:
      +
    • face: an \f$ i\f$-face for some \f$ i\in[0,d]\f$; +
    • vertex: a \f$ 0\f$-face; +
    • edge: a \f$ 1\f$-face; +
    • ridge: a \f$ (d-2)\f$-face; +
    • facet: a \f$ (d-1)\f$-face; +
    • full cell: a \f$ d\f$-face. +
    + +If the vertices are embedded into Euclidean space \f$ \mathbb{R}^n\f$, we deal with -finite simplicial complexes which have slightly different simplices +finite simplicial complexes, which have slightly different simplices and additional requirements:
    • vertices corresponds to points in space. @@ -53,24 +72,21 @@ and additional requirements:
    • the intersection of any two simplices of \f$ S\f$ is a proper face of both simplices (the empty set counts).
    -See the wikipedia -entry for more about simplicial complexes. ## What's in this Package? ## This \cgal package provides four main classes for creating and manipulating triangulations. -The class `CGAL::Triangulation_data_structure` +The class `CGAL::Triangulation_data_structure` models an abstract triangulation: vertices in this class are not embedded in Euclidean space but are only of combinatorial -nature. It deals with simplicial complexes -which are pure, connected and without boundaries nor singularities. +nature. The class `CGAL::Triangulation` describes an embedded triangulation that has as vertices a given set of points. Methods are provided for the insertion of points in the triangulation, the -traversal of various elements of the triangulation, as well as the localization of a +traversal of various elements of the triangulation, as well as the location of a query point inside the triangulation. The triangulation covers the convex hull of the set of points. @@ -84,42 +100,22 @@ any vertex of the triangulation. The class `CGAL::Regular_triangulation` builds the regular triangulation -- also known as weighted Delaunay triangulation -- of a set of points. -A detailed description of such a triangulation is available in section +A detailed definition of such a triangulation is available in section \ref TriangulationSecRT. -## Further Definitions ## - -An \f$ i\f$-face denotes an \f$ i\f$-dimensional simplex, or a simplex with \f$ i+1\f$ -vertices. When these vertices are embedded in Euclidean space, they must be -affinely independent. - -If the maximal dimension of a simplex in the triangulation is -\f$ d\f$, we use the following terminology:
      -
    • face: an \f$ i\f$-face for some \f$ i\in[0,d]\f$; -
    • vertex: a \f$ 0\f$-face; -
    • edge: a \f$ 1\f$-face; -
    • ridge: a \f$ (d-2)\f$-face; -
    • facet: a \f$ (d-1)\f$-face; -
    • full cell: a \f$ d\f$-face. -
    - -Two faces \f$ \sigma\f$ and \f$ \sigma'\f$ are incident if and only if -\f$ \sigma'\f$ is a proper sub-face of \f$ \sigma\f$ or vice versa. - \section TriangulationSecTDS Triangulation Data Structure In this section, we describe the concept `TriangulationDataStructure` for which \cgal provides one model class: -`CGAL::Triangulation_data_structure`. +`CGAL::Triangulation_data_structure`. -A `TriangulationDataStructure` can represent an abstract pure complex -such that any facet is incident to exactly two full cells. +A triangulation data structure can represent an abstract triangulation. -A `TriangulationDataStructure` has a maximal dimension which is a +The maximal dimension of a triangulation data structure is a positive integer equal to the maximum dimension a full cell can have. -This maximal dimension can be chosen by the user at the creation of a -`TriangulationDataStructure` and can then be queried using the method `tds.maximal_dimension()`. -A `TriangulationDataStructure` also knows the current dimension of its full cells, +This maximal dimension can be chosen by the user at the creation of the +triangulation data structure and can then be queried using the method `tds.maximal_dimension()`. +A triangulation data structure also knows the current dimension of its full cells, which can be queried with `tds.current_dimension()`. In the sequel, let us denote the maximal dimension with \f$ D \f$ and the current dimension with \f$ d \f$. The inequalities \f$ -2 \leq d \leq D\f$ and \f$ 0 \le D\f$ always hold. @@ -127,7 +123,7 @@ The special meaning of negative values for \f$d\f$ is explained below. ## The Set of Faces ## -The set of faces of a `TriangulationDataStructure` with +The set of faces of a triangulation data structure with current dimension \f$ d \f$ forms a triangulation of the topological sphere \f$ \mathbb{S}^d\f$. @@ -138,7 +134,7 @@ Possible values of \f$d\f$ (the current dimension of the triangulation) i
    \f$d=-2\f$
    This corresponds to an empty -`TriangulationDataStructure`. +triangulation data structure.
    \f$d=-1\f$
    This corresponds to an abstract simplicial complex reduced to a single vertex. @@ -155,16 +151,16 @@ the sphere \f$ \mathbb{S}^d\f$. ## The `Triangulation_data_structure` Class ## We give here some details about the class -`Triangulation_data_structure` +`Triangulation_data_structure` implementing the concept `TriangulationDataStructure`. ### Storage ### -A `TriangulationDataStructure` explicitly stores its vertices and full cells. +A triangulation data structure explicitly stores its vertices and full cells. Each vertex stores a reference to one of its incident full cells. -Each full cell stores references to its \f$ d+1\f$ vertices and +Each full cell \f$ \sigma \f$ stores references to its \f$ d+1\f$ vertices and neighbors. Its vertices and neighbors are indexed from \f$ 0\f$ to \f$ d \f$. The indices of its neighbors have the following meaning: the \f$ i\f$-th neighbor of \f$ \sigma\f$ is the unique neighbor of \f$ \sigma\f$ that does not contain the \f$ i\f$-th vertex of @@ -206,20 +202,19 @@ documentation of that class template for specific details. ###Template Parameters### -The `Triangulation_data_structure` +The `Triangulation_data_structure` class is designed in such a way that its user can choose
    • the maximal dimension of the triangulation data structure by specifying the `Dimensionality` template parameter, -
    • the type used to represent vertices by specifying the `TriangulationDSVertex` +
    • the type used to represent vertices by specifying the `TriangulationDSVertex_` template parameter and
    • the type used to represent full cells by specifying the -`TriangulationDSFullCell` template parameter. +`TriangulationDSFullCell_` template parameter.
    The last two parameters have default values and are thus not necessary, unless -the user needs custom types (see the reference manual page for this class -template). The first template parameter, `Dimensionality`, must be -one of the following: +the user needs custom types (see `Triangulation_data_structure`). +The first template parameter, `Dimensionality`, must be one of the following:
    • `CGAL::Dimension_tag` for some integer \f$ D \f$. This indicates that the triangulation can store full cells of dimension at most @@ -230,7 +225,7 @@ dimension of the full cells must be passed as an integer argument to an instance constructor (see `TriangulationDataStructure`).
    -The `TriangulationDSVertex` and `TriangulationDSFullCell` parameters to the class template +The `TriangulationDSVertex_` and `TriangulationDSFullCell_` parameters to the class template must be models of the concepts `TriangulationDSVertex` and `TriangulationDSFullCell` respectively. \cgal provides models for these concepts: `Triangulation_ds_vertex` and @@ -241,7 +236,7 @@ some nested types in `TriangulationDataStructure`. The default values are `CGAL::Triangulation_ds_vertex` and `CGAL::Triangulation_ds_full_cell` where `TDS` is the current class -`Triangulation_data_structure`. +`Triangulation_data_structure`. This creates a circular dependency, which we resolve in the same way as in the \cgal `Triangulation_2` and `Triangulation_3` packages (see Chapters \ref Chapter_2D_Triangulation_Data_Structure, \ref Chapter_2D_Triangulations, @@ -306,37 +301,37 @@ Each infinite \f$ i\f$-simplex is incident to the infinite vertex and to an \f$ (i-1)\f$-simplex of the convex hull boundary. -See Chapters \ref Chapter_2D_Triangulations "2D Triangulations" and +See Chapters \ref Chapter_2D_Triangulations "2D Triangulations" or \ref Chapter_3D_Triangulations "3D Triangulations" for more details about infinite vertices and cells. Methods are provided for the insertion of points in the triangulation, the contraction of faces, the traversal of various elements of the triangulation -as well as the localization of a query point inside the triangulation. +as well as the location of a query point inside the triangulation. The ordering of the vertices of a full cell defines an orientation of that full cell. As long as no advanced class method is called, it is guaranteed -that all finite full cells have positive orientation. The infinite full -cells are oriented as if the infinite vertex was on the other side -of the hyperplane supported by the convex hull facets that the other points. +that all finite full cells have positive orientation. Each infinite full +cell is oriented as if its infinite vertex was on the side of +the hyperplane supported by its finite facet where there is no other point. ## Implementation ## The class `CGAL::Triangulation` -stores a model of the concept `TriangulationDataStructure` which is +stores a model of the concept `TriangulationDataStructure` that is instantiated with a vertex type that stores a point. The template parameter `TriangulationTraits` must be a model of the concept -`TriangulationTraits` which provides the `Point` type as well +`TriangulationTraits`, which provides the point type as well as various geometric predicates used by the `Triangulation` class. The `TriangulationTraits` concept includes a nested type -`TriangulationTraits::Dimension` which is the dimension of the predicates. -This dimension governs the number of points given as arguments to the -predicates. This type is either `CGAL::Dimension_tag` or -`CGAL::Dynamic_dimension_tag`. In any case, the dimension of the traits -must match the maximal dimension of the `TriangulationDataStructure`. +`TriangulationTraits::Dimension`. This dimension governs the number of points +given as arguments to the predicates. This type is either +`CGAL::Dimension_tag` or `CGAL::Dynamic_dimension_tag`. +In any case, the dimension of the traits +must match the maximal dimension of the triangulation data structure. The template parameter `TriangulationDataStructure` must be a model of the concept `TriangulationDataStructure` which provides the triangulation data @@ -419,7 +414,7 @@ hole is ``star shaped'' around `p` and thus is re-triangulated using `p` as a center vertex. Delaunay triangulations support insertion of points, removal of vertices, -and localization of a query point inside the triangulation. +and location of a query point inside the triangulation. Note that inserting a set of points at once is much faster than inserting the points one by one. @@ -484,7 +479,7 @@ A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres of all simplices are regular. Regular triangulations support insertion of points, -and localization of a query point inside the triangulation. +and location of a query point inside the triangulation. Note that inserting a set of points at once is much faster than inserting the points one by one. \warning The removal of vertices is not supported yet. From 5e8137ad3ffdb712e676d924af506d147087b7ef Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 11 Mar 2016 10:44:20 +0100 Subject: [PATCH 418/487] Monique's review - part 2 (User manual) --- Triangulation/doc/Triangulation/Triangulation.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 24ddb39da14..e03b47af130 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -422,14 +422,14 @@ than inserting the points one by one. The class `CGAL::Delaunay_triangulation` derives from `CGAL::Triangulation`. It thus stores a model of -the concept `TriangulationDataStructure` which is instantiated with a vertex +the concept `TriangulationDataStructure`, which is instantiated with a vertex type that stores a geometric point and allows its retrieval. The template parameter `DelaunayTriangulationTraits` must be a model of the concept `DelaunayTriangulationTraits` which provides the geometric `Point` type as well as various geometric predicates used by the `Delaunay_triangulation` class. The concept `DelaunayTriangulationTraits` refines the concept -`TriangulationTraits` by requiring a few other geometric predicates, necessary +`TriangulationTraits` by requiring a few additional geometric predicates, necessary for the computation of Delaunay triangulations. ## Examples ## @@ -478,7 +478,7 @@ called the power sphere. A sphere \f$ {z}^{(w)}\f$ is said to be A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres of all simplices are regular. -Regular triangulations support insertion of points, +Regular triangulations support insertion of weighted points, and location of a query point inside the triangulation. Note that inserting a set of points at once is much faster than inserting the points one by one. @@ -493,7 +493,7 @@ the concept `TriangulationDataStructure` which is instantiated with a vertex type that stores a weighted point and allows its retrieval. The template parameter `RegularTriangulationTraits` must be a model of the concept -`RegularTriangulationTraits` which provides the and `%Weighted_point` +`RegularTriangulationTraits`. It must provide the `%Weighted_point` type as well as various geometric predicates used by the `Regular_triangulation` class. The concept `RegularTriangulationTraits` refines the concept From 9d8e3fb03e051f98b51e66e7ca33a0b830e4731a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 16 Mar 2016 17:44:37 +0100 Subject: [PATCH 419/487] Export to RIB (RenderMan) Can be rendered using Pixie --- .../CGAL/Tangential_complex/RIB_exporter.h | 288 ++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/RIB_exporter.h diff --git a/Tangential_complex/include/CGAL/Tangential_complex/RIB_exporter.h b/Tangential_complex/include/CGAL/Tangential_complex/RIB_exporter.h new file mode 100644 index 00000000000..fb19551e8e1 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/RIB_exporter.h @@ -0,0 +1,288 @@ +// Copyright (c) 2016 INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin + +#ifndef CGAL_TC_WRITE_RIB_FILE_H +#define CGAL_TC_WRITE_RIB_FILE_H + +#include "utilities.h" + +#include + +#include +#include + +namespace CGAL { +namespace Tangential_complex_ { + +template +class RIB_exporter +{ + typedef typename PointRandomAccessRange::value_type Point; +public: + + typedef std::tuple Color; // RGBA + + // Constructor + RIB_exporter( + PointRandomAccessRange const& points, + SimplexRange const& simplices, + std::ofstream &out, + std::string const& rendered_image_filename = "export.tif", + bool is_preview = false, // low-quality + int image_width = 1920, + int image_height = 1080, + Color const& triangle_color = std::make_tuple(0., 1., 1., 1.), + bool ambient_light = true, + double ambient_intensity = 0.20, + bool shadow = true, + double shadow_intensity = 0.85) + : m_points(points), + m_simplices(simplices), + m_out(out), + m_rendered_image_filename(rendered_image_filename), + m_is_preview(is_preview), + m_image_width(image_width), + m_image_height(image_height), + m_current_color(0., 0., 0., 0.), + m_current_alpha(1), + m_triangle_color(triangle_color), + m_ambient_light(ambient_light), + m_ambient_intensity(ambient_intensity), + m_shadow(shadow), + m_shadow_intensity(shadow_intensity) + { + m_out.precision(8); + } + + void write_file() + { + write_header(); + write_lights(); + write_triangles(); + + m_out << "WorldEnd\n"; + } + +private: + + void write_header() + { + m_out << "Option \"searchpath\" \"shader\" " + "\".:./shaders:%PIXIE_SHADERS%:%PIXIEHOME%/shaders\"\n"; + + if (m_is_preview) + { + m_out << "Attribute \"visibility\" \"specular\" 1\n" + << "Attribute \"visibility\" \"transmission\" 1\n\n"; + } + + m_out << "Display \"" << m_rendered_image_filename << "\" \"file\" \"rgb\"\n"; + + if (!m_is_preview) + { + m_out << "Format " << m_image_width << " " << m_image_height << " 1\n"; + } + else + { + double ratio = double(m_image_height) / double(m_image_width); + + int width = (ratio < 1.) ? 300 : int(300. / ratio); + int height = (ratio < 1.) ? int(ratio * 300.) : 300; + + m_out << "Format " << width << " " << height << " 1\n"; + } + + + if (m_image_width > m_image_height) + { + double ratio = double(m_image_height) / double(m_image_width); + m_out << "ScreenWindow -1 1 " << -ratio << " " << ratio << "\n"; + } + else if (m_image_height > m_image_width) + { + double ratio = double(m_image_width) / double(m_image_height); + m_out << "ScreenWindow " << -ratio << " " << ratio << " -1 1\n"; + } + + m_out << "Projection \"perspective\" \"fov\" 45\n" + << "Translate 0 0 15\n" + << "PixelSamples 4 4\n" + << "PixelFilter \"catmull-rom\" 3 3\n" + << "ShadingInterpolation \"smooth\"\n" + << "Rotate 180 0 0 1\n" + << "WorldBegin\n"; + } + + + void write_lights() + { + if (!m_is_preview) + { + // ShadowLight + m_out << "LightSource \"shadowdistant\" 1 \"from\" [0 0 0] \"to\" [0 0 1]" + << " \"shadowname\" \"raytrace\" \"intensity\" " + << m_shadow_intensity << "\n"; + + // Ambient light + m_out << "LightSource \"ambientlight\" 2 \"intensity\" " + << m_ambient_intensity << "\n"; + } + else + { + m_out << "LightSource \"distantLight\" 1 \"from\" [0 0 0] \"to\" [0 0 1]" + << " \"intensity\" 0.85\n"; + } + + // Background light + m_out << "LightSource \"ambientlight\" 99 \"intensity\" 1\n"; + + // Turn background light OFF + turn_background_light(false); + } + + void turn_background_light(bool turn_on) + { + if (!turn_on) + { + m_out << "Illuminate 1 1" << std::endl; + if (!m_is_preview) + m_out << "Illuminate 2 1" << std::endl; + m_out << "Illuminate 99 0" << std::endl; + } + else + { + m_out << "Illuminate 1 0" << std::endl; + if (!m_is_preview) + m_out << "Illuminate 2 0" << std::endl; + m_out << "Illuminate 99 1" << std::endl; + } + } + + // CJTODO + void write_background(const Color& color) + { + write_turn_background_light(false); + + /*m_out << "Surface \"constant\"" << std::endl; + write_color(color, false); + + double corner = zmax_ * 2.; + double depth_pos = zmax_ * 1.6; + + m_out << "Polygon \"P\" ["; + m_out << " " << -corner << " " << -corner << " " << depth_pos << " "; + m_out << " " << corner << " " << -corner << " " << depth_pos << " "; + m_out << " " << corner << " " << corner << " " << depth_pos << " "; + m_out << " " << -corner << " " << corner << " " << depth_pos << " "; + m_out << "]" << std::endl;*/ + } + + + void write_color(Color const& color, bool use_transparency) + { + if (m_current_color == color) + return; + + m_current_color = color; + + // Write opacity data + if (use_transparency) + write_opacity(std::get<3>(color)); + + // Write color data + m_out << "Color [ " << std::get<0>(color) << " " << std::get<1>(color) + << " " << std::get<2>(color) << " ]\n"; + } + + void write_opacity(const double alpha) + { + if (m_current_alpha == alpha) + return; + + m_current_alpha = alpha; + + // Write opacity data + m_out << "Opacity " << alpha << " " << alpha << " " << alpha << std::endl; + } + + void write_point(Point const& p) + { + m_out << " " << p[0] << " " << p[1] << " " << p[2] << " "; + } + + void write_triangles() + { + m_out << "Surface \"plastic\" \"Ka\" 0.65 \"Kd\" 0.85 \"Ks\" 0.25 \"roughness\" 0.1" << std::endl; + + for (auto simplex : m_simplices) + { + std::vector > triangles; + // Get the triangles composing the simplex + combinations(simplex, 3, std::back_inserter(triangles)); + for (auto const& t : triangles) + write_triangle(t); + } + } + + template + void write_triangle(PointIndexRange const& t) + { + // Color + write_color(m_triangle_color, true); + + // Triangle + m_out << "Polygon \"P\" ["; + for (auto idx : t) + write_point(m_points[idx]); + m_out << "]" << std::endl; + + // Edges (will be drawn later on) + /*add_edge(p, q, edge_color); + add_edge(p, r, edge_color); + add_edge(q, r, edge_color); + + // Vertices (will be drawn later on) + add_vertex(p, edge_color); + add_vertex(q, edge_color); + add_vertex(r, edge_color);*/ + } + + //=========================================================================== + + PointRandomAccessRange const& m_points; + SimplexRange const& m_simplices; + std::ofstream &m_out; + std::string m_rendered_image_filename; + bool m_is_preview; + int m_image_width; + int m_image_height; + Color m_current_color; + Color m_triangle_color; + double m_current_alpha; + bool m_ambient_light; + double m_ambient_intensity; + bool m_shadow; + double m_shadow_intensity; +}; + +} // namespace Tangential_complex_ +} //namespace CGAL + +#endif // CGAL_TC_WRITE_RIB_FILE_H From 80aefa2a6ba3d0b59f4650ead85fc1862d8c8bdd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 May 2016 17:24:47 +0200 Subject: [PATCH 420/487] Fixes according to Samuel's review + fixes from live review with Monique --- .../CGAL/Regular_triangulation.h | 4 +- .../doc/Triangulation/CGAL/Triangulation.h | 2 +- .../Concepts/DelaunayTriangulationTraits.h | 2 +- .../Concepts/RegularTriangulationTraits.h | 43 +++++++++---------- .../doc/Triangulation/Triangulation.txt | 16 +++---- 5 files changed, 32 insertions(+), 35 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index b2ff04a315c..d7e0c19800d 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -53,7 +53,7 @@ public: /// @{ /*! -A point in Euclidean space. +A point in Euclidean space with an associated weight. */ typedef RegularTriangulationTraits::Weighted_point Weighted_point; @@ -107,7 +107,7 @@ Inserts the weighted points found in range `[s,e)` in the regular triangulation. Returns the difference of the number of vertices between after and before the insertions (it may be negative due to hidden points). Note that this function is not guaranteed to insert the points -following the order of `InputIterator`, as `spatial_sort()` +following the order of `ForwardIterator` because `spatial_sort()` is used to improve efficiency. \tparam ForwardIterator must be an input iterator with the value diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index 14ab0eb2630..e0069c34e75 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -49,7 +49,7 @@ full cell, plus the non-combinatorial information about each full cell, then the indices of the neighbors of each full cell, where the index corresponds to the preceding list of full cells. -\sa `Triangulation_data_structure` +\sa `Triangulation_data_structure` \sa `Delaunay_triangulation` */ diff --git a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h index f575caea9ee..6211c847176 100644 --- a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h @@ -79,7 +79,7 @@ DelaunayTriangulationTraits(); /// @} /// \name Operations -/// The following methods permit access to the traits class's predicates: +/// The following methods permit access to the traits class's predicates and functors: /// @{ /*! diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index c6f5bd091b3..31fc0d13a70 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -10,8 +10,6 @@ a regular triangulation. It corresponds to the first template parameter of the c \cgalRefines ::TriangulationTraits. \cgalHasModel `CGAL::Epick_d` - -\sa `TriangulationTraits` */ class RegularTriangulationTraits { public: @@ -20,9 +18,9 @@ public: /// @{ /*! -An arithmetic field type. +A number type that is a model for `RingNumberType`. */ -typedef unspecified_type FT; +typedef unspecified_type RT; /*! The weighted point type. @@ -30,35 +28,35 @@ The weighted point type. typedef unspecified_type Weighted_point_d; /*! -A predicate object that must provide the operator +A function object that must provide the operator `Point_d operator()(const Weighted_point & wp)`, returning `wp` without its weight. */ typedef unspecified_type Point_drop_weight_d; /*! -A predicate object that must provide the operator -`FT operator()(const Weighted_point & wp)`, returning +A function object that must provide the operator +`RT operator()(const Weighted_point & wp)`, returning the weight of `wp`. */ typedef unspecified_type Point_weight_d; /*! A predicate object that must provide the templated operator -`template Oriented_side operator()(ForwardIterator start, ForwardIterator end, const Point_d & p)`. +`template Oriented_side operator()(ForwardIterator start, ForwardIterator end, const Weighted_point_d & p)`. Let \f$ S \f$ be the power sphere of the weighted points in range `[start,end)`. The operator returns: - `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to \f$ S \f$, -- `ON_NEGATIVE_SIDE` if `p` lies outside the oriented sphere of - the same center as \f$ S \f$ and radius \f$ \sqrt{ w_S^2 + w_p^2 }\f$, +- `ON_NEGATIVE_SIDE` if the power distance between `p` and \f$ S \f$ is +positive. -- `ON_POSITIVE_SIDE` if `p` lies inside this oriented sphere. +- `ON_POSITIVE_SIDE` otherwise. -\pre If `Dimension`=`CGAL::Dimension_tag`, +\pre If `Dimension` is `CGAL::Dimension_tag`, then `std::distance(start,end)=D+1`. -The points in range +The weighted points in range `[start,end)` must be affinely independent, i.e., the simplex must not be flat. */ @@ -66,9 +64,9 @@ typedef unspecified_type Power_test_d; /*! A predicate object that must provide the templated operator -`template Oriented_side operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end, const Point_d & p)`. +`template Oriented_side operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end, const Weighted_point_d & p)`. -The points in range `[start,end)` and `p` are supposed to belong to the lower dimensional flat +The points in range `[start,end)` and `p` are supposed to belong to the lower-dimensional flat whose orientation is given by `orient`. Let \f$ S \f$ be the power sphere of the weighted points in range `[start,end)` @@ -77,16 +75,15 @@ The operator returns: - `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to \f$ S \f$, -- `ON_NEGATIVE_SIDE` if `p` lies outside the oriented sphere of -the same center as \f$ S \f$ and radius \f$ \sqrt{ w_S^2 + w_p^2 }\f$, +- `ON_NEGATIVE_SIDE` if the power distance between `p` and \f$ S \f$ is +positive. -- `ON_POSITIVE_SIDE` if `p` lies inside this oriented sphere. +- `ON_POSITIVE_SIDE` otherwise. \pre `std::distance(start,end)=k+1` where \f$ k\f$ is the number of -points used to construct `orient`. -The points in range -`[start,end)` must be affinely independent, i.e., the simplex must -not be flat. `p` must be in the flat generated by this simplex. +points used to construct `orient` (dimension of the flat). +The points in range `[start,end)` must be affinely independent. +`p` must be in the flat generated by these points. */ typedef unspecified_type In_flat_power_test_d; @@ -105,7 +102,7 @@ RegularTriangulationTraits(); /// @} /// \name Operations -/// The following methods permit access to the traits class's predicates: +/// The following methods permit access to the traits class's predicates and functors: /// @{ /*! diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index e03b47af130..3d1c3137122 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -32,7 +32,7 @@ singular of which is simplex). A simplex \f$ s\in S\f$ is maximal if it is not a proper subset of some other set in \f$ S\f$. A simplex having \f$ k+1 \f$ vertices is said of dimension \f$ k \f$. -An \f$ k\f$-face denotes a \f$ k\f$-dimensional simplex, or a simplex with \f$ k+1\f$ +An \f$ k\f$-face denotes a \f$ k\f$-dimensional simplex, i.e., a simplex with \f$ k+1\f$ vertices. The simplicial complex is pure if all the maximal simplices have the same dimension. @@ -66,7 +66,7 @@ we deal with finite simplicial complexes, which have slightly different simplices and additional requirements:
      -
    • vertices corresponds to points in space. +
    • vertices correspond to points in space.
    • a simplex \f$ s\in S\f$ is the convex hull of its vertices.
    • the vertices of a simplex \f$ s\in S\f$ are affinely independent.
    • the intersection of any two simplices of \f$ S\f$ is a proper face of both @@ -114,9 +114,9 @@ A triangulation data structure can represent an abstract triangulation. The maximal dimension of a triangulation data structure is a positive integer equal to the maximum dimension a full cell can have. This maximal dimension can be chosen by the user at the creation of the -triangulation data structure and can then be queried using the method `tds.maximal_dimension()`. +triangulation data structure and can then be obtained using the method `tds.maximal_dimension()`. A triangulation data structure also knows the current dimension of its full cells, -which can be queried with `tds.current_dimension()`. In the sequel, let +which can be obtained using `tds.current_dimension()`. In the sequel, let us denote the maximal dimension with \f$ D \f$ and the current dimension with \f$ d \f$. The inequalities \f$ -2 \leq d \leq D\f$ and \f$ 0 \le D\f$ always hold. The special meaning of negative values for \f$d\f$ is explained below. @@ -415,8 +415,8 @@ hole is ``star shaped'' around `p` and thus is re-triangulated using Delaunay triangulations support insertion of points, removal of vertices, and location of a query point inside the triangulation. -Note that inserting a set of points at once is much faster -than inserting the points one by one. +Note that inserting a large set of points at once is much faster +than inserting the same points one by one. ## Implementation ## @@ -480,8 +480,8 @@ of all simplices are regular. Regular triangulations support insertion of weighted points, and location of a query point inside the triangulation. -Note that inserting a set of points at once is much faster -than inserting the points one by one. +Note that inserting a large set of points at once is much faster +than inserting the same points one by one. \warning The removal of vertices is not supported yet. From ab30798119caea88e975919b53987ab443c15067 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 May 2016 17:27:30 +0200 Subject: [PATCH 421/487] Make the use of Regular_triangulation_euclidean_traits explicit --- .../Triangulation/delaunay_triangulation.cpp | 91 ++++++------------- .../include/CGAL/Regular_triangulation.h | 8 +- .../Regular_triangulation_euclidean_traits.h | 2 +- .../test/Triangulation/test_regular.cpp | 2 +- 4 files changed, 36 insertions(+), 67 deletions(-) diff --git a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp index 0d186f452bf..e4210a31569 100644 --- a/Triangulation/examples/Triangulation/delaunay_triangulation.cpp +++ b/Triangulation/examples/Triangulation/delaunay_triangulation.cpp @@ -1,70 +1,39 @@ #include -#include #include -#include -#include -#include -#include -#include -#include - -const int D=5; -typedef CGAL::Epick_d< CGAL::Dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - -int main(int argc, char **argv) +int main() { - int N = 100; // number of points - if( argc > 1 ) - N = atoi(argv[1]); - CGAL::Timer cost; // timer + double pointsIn[][7] = { + { 42.89, 0, 60.55, 30.72, 0, 0, 0 }, + { 45.65, 50.83, 50.37, 16.13, 0, 0, 0 }, + { 79.06, 57.84, 61.59, 2.52, 0, 0, 0 }, + { 44.47, 39.46, 39.53, 28.72, 0, 0, 0 }, + { 0, 100, 0, 0, 100, 0, 53.47 }, + { 66.95, 100, 33.6, 0, 0, 0, 0 }, + { 42.89, 0, 0, 30.72, 100, 0, 53.47 }, + { 100, 100, 100, 100, 100, 100, 100 } + }; + + typedef CGAL::Triangulation > > T; + T dt(7); - // Generate N random points - typedef CGAL::Random_points_in_cube_d Random_points_iterator; - Random_points_iterator rand_it(D, 1.0, CGAL::get_default_random()); std::vector points; - CGAL::cpp11::copy_n(rand_it, N, std::back_inserter(points)); - - T t(D); - CGAL_assertion(t.empty()); - - // insert the points in the triangulation - cost.reset(); - cost.start(); - std::cout << " Delaunay triangulation of " << N << " points in dim " << D - << std::flush; - t.insert(points.begin(), points.end()); - std::cout << " done in " << cost.time() << " seconds." << std::endl; - CGAL_assertion( t.is_valid() ); - - // insert with special operations in conflict zone and new created cells - cost.reset(); - std::cout << " adding " << N << " other points " << std::endl; - for (int i = 0 ; i < N ; ++i) - { - T::Vertex_handle v; - T::Face f(t.current_dimension()); - T::Facet ft; - T::Full_cell_handle c; - T::Locate_type lt; - typedef std::vector Full_cells; - Full_cells zone, new_full_cells; - std::back_insert_iterator out(zone); - c = t.locate(*++rand_it, lt, f, ft, v); - - // Previously inserted vertex v is used as hint for point location (if defined) - T::Facet ftc = t.compute_conflict_zone(*rand_it, c, out); - std::cout << i << " conflict zone of size: " << zone.size() << " -> " - << std::flush; - out = std::back_inserter(new_full_cells); - CGAL_assertion(t.is_valid()); - v = t.insert_in_hole(*rand_it, zone.begin(), zone.end(), ftc, out); - std::cout << new_full_cells.size() << " new cells" << std::endl; + points.reserve(8); + for (int j = 0; j < 8; ++j) { + T::Point p(&pointsIn[j][0], &pointsIn[j][7]); + points.push_back(p); } - std::cout << " done in " << cost.time() << " seconds." << std::endl; + T::Vertex_handle hint; + int i = 0; + for (std::vector::iterator it = points.begin(); it != points.end(); ++it) { + if (T::Vertex_handle() != hint) { + hint = dt.insert(*it, hint); + } + else { + hint = dt.insert(*it); + } + printf("Processing: %d/%d\n", ++i, (int)points.size()); + } return 0; -} +} \ No newline at end of file diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 308671521af..2a02b099b46 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -33,17 +33,17 @@ namespace CGAL { template< typename Traits_, typename TDS_ = Default > class Regular_triangulation : public Triangulation< - CGAL::Regular_triangulation_euclidean_traits, + Traits_, typename Default::Get< TDS_, Triangulation_data_structure< typename Traits_::Dimension, - Triangulation_vertex >, - Triangulation_full_cell > + Triangulation_vertex, + Triangulation_full_cell > >::type> { - typedef CGAL::Regular_triangulation_euclidean_traits RTTraits; + typedef Traits_ RTTraits; typedef typename RTTraits::Dimension Maximal_dimension_; typedef typename Default::Get< TDS_, diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index ec701ee2713..893de15a790 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -26,7 +26,7 @@ namespace CGAL { -template < class K, class Weight = typename K::RT > +template class Regular_triangulation_euclidean_traits : public K { diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index fc319e39ff0..8f30b9f679f 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -109,7 +109,7 @@ void go(const int N) { //typedef CGAL::Epick_d FK; typedef CGAL::Epick_d > FK; - typedef CGAL::Regular_triangulation Triangulation; + typedef CGAL::Regular_triangulation > Triangulation; //test(D, "dynamic", N); test(D, "static", N); } From 4ae4901e6fb07f151581c4d88b1f716b79ecf9a7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 May 2016 17:38:06 +0200 Subject: [PATCH 422/487] Remove debug or useless code --- Triangulation/test/Triangulation/test_regular.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index 8f30b9f679f..a4dc13260c8 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -29,8 +29,6 @@ void test(const int d, const string & type, const int N) assert(rt.empty()); vector points; - //CGAL::Random rng; - //Random_points_iterator rand_it(d, 2.0, rng); // CJTODO: unused srand(10); for( int i = 0; i < N; ++i ) @@ -40,7 +38,7 @@ void test(const int d, const string & type, const int N) coords[j] = static_cast(rand() % 100000)/10000; points.push_back(Point( Bare_point(d, coords.begin(), coords.end()), - /*static_cast(rand() % 100000)/100000*/static_cast(i)/20 + static_cast(rand() % 100000)/100000 )); } rt.insert(points.begin(), points.end()); From 3e947585bea1d96c17c6979d4987008aa953d996 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 May 2016 18:33:58 +0200 Subject: [PATCH 423/487] Fix template parameters names (add _ when necessary) --- .../CGAL/Delaunay_triangulation.h | 18 +++--- .../CGAL/Regular_triangulation.h | 20 +++--- .../doc/Triangulation/CGAL/Triangulation.h | 62 +++++++++---------- .../CGAL/Triangulation_data_structure.h | 10 +-- .../CGAL/Triangulation_ds_full_cell.h | 8 +-- .../CGAL/Triangulation_ds_vertex.h | 10 +-- .../Triangulation/CGAL/Triangulation_face.h | 4 +- .../CGAL/Triangulation_full_cell.h | 16 ++--- .../Triangulation/CGAL/Triangulation_vertex.h | 22 +++---- .../Concepts/DelaunayTriangulationTraits.h | 2 +- .../Concepts/RegularTriangulationTraits.h | 2 +- .../Concepts/TriangulationDSFace.h | 2 +- .../Concepts/TriangulationDSFullCell.h | 4 +- .../Concepts/TriangulationDSVertex.h | 2 +- .../Concepts/TriangulationDataStructure.h | 14 ++--- .../Concepts/TriangulationFullCell.h | 8 +-- .../Concepts/TriangulationTraits.h | 2 +- .../Concepts/TriangulationVertex.h | 10 +-- .../doc/Triangulation/PackageDescription.txt | 16 ++--- .../doc/Triangulation/Triangulation.txt | 46 +++++++------- 20 files changed, 139 insertions(+), 139 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h index 338e62d4b74..2bfd69459b4 100644 --- a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h @@ -22,19 +22,19 @@ having all vertices of the simplex on its boundary. Parameters -------------- -\tparam DelaunayTriangulationTraits is the geometric traits class that provides the geometric types -and predicates needed by Delaunay triangulations. `DelaunayTriangulationTraits` must be a model of +\tparam DelaunayTriangulationTraits_ is the geometric traits class that provides the geometric types +and predicates needed by Delaunay triangulations. `DelaunayTriangulationTraits_` must be a model of the concept `DelaunayTriangulationTraits`. -\tparam TriangulationDataStructure must be a model of the concept +\tparam TriangulationDataStructure_ must be a model of the concept `TriangulationDataStructure`. This model is used to store -the faces of the triangulation. The parameter `TriangulationDataStructure` defaults to +the faces of the triangulation. The parameter `TriangulationDataStructure_` defaults to `Triangulation_data_structure` whose template parameters are instantiated as follows:
        -
      • `DelaunayTriangulationTraits::Dimension`
      • -
      • `Triangulation_vertex`
      • -
      • `Triangulation_full_cell`.
      • +
      • `DelaunayTriangulationTraits_::Dimension`
      • +
      • `Triangulation_vertex`
      • +
      • `Triangulation_full_cell`.
      \tparam Delaunay_triangulation can @@ -45,9 +45,9 @@ tag `CGAL::Default` as the second parameter. \sa `Triangulation_data_structure` */ -template< typename DelaunayTriangulationTraits, typename TriangulationDataStructure > +template< typename DelaunayTriangulationTraits_, typename TriangulationDataStructure_ > class Delaunay_triangulation - : public Triangulation + : public Triangulation { public: diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index d7e0c19800d..7713b0972d2 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -19,20 +19,20 @@ User Manual. Parameters -------------- -\tparam RegularTriangulationTraits is the geometric traits class that provides the +\tparam RegularTriangulationTraits_ is the geometric traits class that provides the geometric types and predicates needed by regular triangulations. -`RegularTriangulationTraits` must be a model of the concept +`RegularTriangulationTraits_` must be a model of the concept `RegularTriangulationTraits`. -\tparam TriangulationDataStructure must be a model of the concept +\tparam TriangulationDataStructure_ must be a model of the concept `TriangulationDataStructure`. This model is used to store -the faces of the triangulation. The parameter `TriangulationDataStructure` +the faces of the triangulation. The parameter `TriangulationDataStructure_` defaults to `Triangulation_data_structure` whose template parameters are instantiated as follows:
        -
      • `RegularTriangulationTraits::Dimension`
      • -
      • `Triangulation_vertex >`
      • -
      • `Triangulation_full_cell >`.
      • +
      • `RegularTriangulationTraits_::Dimension`
      • +
      • `Triangulation_vertex >`
      • +
      • `Triangulation_full_cell >`.
      \tparam Regular_triangulation can @@ -43,9 +43,9 @@ tag `CGAL::Default` as the second parameter. \sa `Triangulation_data_structure` */ -template< typename RegularTriangulationTraits, typename TriangulationDataStructure > +template< typename RegularTriangulationTraits_, typename TriangulationDataStructure_ > class Regular_triangulation - : public Triangulation + : public Triangulation { public: @@ -55,7 +55,7 @@ public: /*! A point in Euclidean space with an associated weight. */ -typedef RegularTriangulationTraits::Weighted_point Weighted_point; +typedef RegularTriangulationTraits_::Weighted_point Weighted_point; /// @} diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index e0069c34e75..8e9922eb48c 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -19,25 +19,25 @@ convex hull boundary. Parameters -------------- -`TriangulationTraits` is the geometric traits class that provides the geometric types -and predicates needed by triangulations. `TriangulationTraits` must be a model of the +`TriangulationTraits_` is the geometric traits class that provides the geometric types +and predicates needed by triangulations. `TriangulationTraits_` must be a model of the concept `TriangulationTraits`. -The parameter `TriangulationDataStructure` must be a model of the concept +The parameter `TriangulationDataStructure_` must be a model of the concept `TriangulationDataStructure`. This model is used to store -the faces of the triangulation. The parameter `TriangulationDataStructure` defaults to +the faces of the triangulation. The parameter `TriangulationDataStructure_` defaults to `Triangulation_data_structure` whose template parameters are instantiated as follows:
        -
      • `DelaunayTriangulationTraits::Dimension`
      • -
      • `Triangulation_vertex`
      • -
      • `Triangulation_full_cell`.
      • +
      • `TriangulationTraits_::Dimension`
      • +
      • `Triangulation_vertex`
      • +
      • `Triangulation_full_cell`.
      The triangulation deduces its maximal dimension from the type -`TriangulationTraits::Dimension`. This dimension has to match +`TriangulationTraits_::Dimension`. This dimension has to match the dimension returned by -`TriangulationDataStructure::maximal_dimension()`. +`TriangulationDataStructure_::maximal_dimension()`. Input/Output -------------- @@ -50,24 +50,24 @@ indices of the neighbors of each full cell, where the index corresponds to the preceding list of full cells. \sa `Triangulation_data_structure` -\sa `Delaunay_triangulation` +\sa `Delaunay_triangulation` */ -template< typename TriangulationTraits, typename TriangulationDataStructure > +template< typename TriangulationTraits_, typename TriangulationDataStructure_> class Triangulation { public: /// \name Types /// @{ /*! -Type for the model of the `TriangulationTraits` concept. +Type for the model of the `TriangulationTraits_` concept. */ -typedef TriangulationTraits Geom_traits; +typedef TriangulationTraits_ Geom_traits; /*! A point in Euclidean space. */ -typedef TriangulationTraits::Point_d Point; +typedef TriangulationTraits_::Point_d Point; /*! This indicates whether the maximal dimension is static @@ -77,34 +77,34 @@ or dynamic (i.e.\ if the type of `Maximal_dimension` is In the latter case, the `dim` parameter passed to the class's constructor is used. */ -typedef TriangulationTraits::Dimension Maximal_dimension; +typedef TriangulationTraits_::Dimension Maximal_dimension; /*! The second template parameter: the triangulation data structure. */ -typedef TriangulationDataStructure Triangulation_ds; +typedef TriangulationDataStructure_ Triangulation_ds; /*! A model of the concept `TriangulationVertex`. */ -typedef TriangulationDataStructure::Vertex Vertex; +typedef TriangulationDataStructure_::Vertex Vertex; /*! A model of the concept `TriangulationFullCell`. */ -typedef TriangulationDataStructure::Full_cell Full_cell; +typedef TriangulationDataStructure_::Full_cell Full_cell; /*! The facet class */ -typedef TriangulationDataStructure::Facet Facet; +typedef TriangulationDataStructure_::Facet Facet; /*! A model of the concept `TriangulationDSFace`. */ -typedef TriangulationDataStructure::Face Face; +typedef TriangulationDataStructure_::Face Face; /// @} @@ -124,25 +124,25 @@ typedef TriangulationDataStructure::Face Face; /*! handle to a a vertex */ -typedef TriangulationDataStructure::Vertex_handle +typedef TriangulationDataStructure_::Vertex_handle Vertex_handle; /*! const handle to a a vertex */ -typedef TriangulationDataStructure::Vertex_const_handle +typedef TriangulationDataStructure_::Vertex_const_handle Vertex_const_handle; /*! iterator over all vertices (including the infinite one) */ -typedef TriangulationDataStructure::Vertex_iterator +typedef TriangulationDataStructure_::Vertex_iterator Vertex_iterator; /*! const iterator over all vertices (including the infinite one) */ -typedef TriangulationDataStructure::Vertex_const_iterator +typedef TriangulationDataStructure_::Vertex_const_iterator Vertex_const_iterator; /*! @@ -158,27 +158,27 @@ typedef unspecified_type Finite_vertex_const_iterator; /*! handle to a full cell */ -typedef TriangulationDataStructure::Full_cell_handle +typedef TriangulationDataStructure_::Full_cell_handle Full_cell_handle; /*! const handle to a full cell */ -typedef TriangulationDataStructure::Full_cell_const_handle +typedef TriangulationDataStructure_::Full_cell_const_handle Full_cell_const_handle; /*! iterator over all full cells (including the infinite ones) */ typedef -TriangulationDataStructure::Full_cell_iterator +TriangulationDataStructure_::Full_cell_iterator Full_cell_iterator; /*! const iterator over all full cells (including the infinite ones) */ typedef -TriangulationDataStructure::Full_cell_const_iterator +TriangulationDataStructure_::Full_cell_const_iterator Full_cell_const_iterator; /*! @@ -194,7 +194,7 @@ typedef unspecified_type Finite_full_cell_const_iterator; /*! iterator over all facets (including the infinite ones) */ -typedef TriangulationDataStructure::Facet_iterator +typedef TriangulationDataStructure_::Facet_iterator Facet_iterator; /*! @@ -206,13 +206,13 @@ typedef unspecified_type Finite_facet_iterator; Size type (an unsigned integral type). */ -typedef TriangulationDataStructure::size_type size_type; +typedef TriangulationDataStructure_::size_type size_type; /*! Difference type (a signed integral type). */ -typedef TriangulationDataStructure::difference_type difference_type; +typedef TriangulationDataStructure_::difference_type difference_type; /*! specifies which case occurs when locating a point in the triangulation. diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation_data_structure.h b/Triangulation/doc/Triangulation/CGAL/Triangulation_data_structure.h index 9d374c693f8..a9af5d2c58e 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation_data_structure.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation_data_structure.h @@ -21,21 +21,21 @@ triggers some optimizations. Or dimension of the simplices (full cells) is passed as an integer argument to an instance constructor (see `TriangulationDataStructure`).
    -The template parameter `TriangulationDSVertex` stands for a class to +The template parameter `TriangulationDSVertex_` stands for a class to be used as the base `Vertex` type in the triangulation data structure. It must be a model of the concept `TriangulationDSVertex`. The class template `Triangulation_data_structure` can be defined by specifying only the first parameter. It also accepts the tag `CGAL::Default` as -second parameter. In both cases, `TriangulationDSVertex` defaults to +second parameter. In both cases, `TriangulationDSVertex_` defaults to `CGAL::Triangulation_ds_vertex<>`. -The template parameter `TriangulationDSFullCell` stands for a class to +The template parameter `TriangulationDSFullCell_` stands for a class to be used as the base `Full_cell` type in the triangulation data structure. It must be a model of the concept `TriangulationDSFullCell`. The class template `Triangulation_data_structure` accepts that no third parameter be specified. It also accepts the tag `CGAL::Default` as -third parameter. In both cases, `TriangulationDSFullCell` defaults to +third parameter. In both cases, `TriangulationDSFullCell_` defaults to `CGAL::Triangulation_ds_full_cell<>`. \cgalModels `TriangulationDataStructure`. In addition, the class @@ -45,7 +45,7 @@ methods. \sa `Triangulation_ds_vertex` \sa `Triangulation_ds_full_cell` */ -template< typename Dimensionality, typename TriangulationDSVertex, typename TriangulationDSFullCell > +template< typename Dimensionality, typename TriangulationDSVertex_, typename TriangulationDSFullCell_ > class Triangulation_data_structure { public: diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation_ds_full_cell.h b/Triangulation/doc/Triangulation/CGAL/Triangulation_ds_full_cell.h index 2828f2b191a..76a517d06df 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation_ds_full_cell.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation_ds_full_cell.h @@ -19,7 +19,7 @@ with some additional attributes tuned for a specific application. Parameters -------------- -The first template parameter, `TriangulationDataStructure`, must be a model of the +The first template parameter, `TriangulationDataStructure_`, must be a model of the `TriangulationDataStructure` concept. The second parameter, `TriangulationDSFullCellStoragePolicy`, indicates whether or not @@ -55,11 +55,11 @@ Rebind mechanism In case of derivation from that class, the nested class `Rebind_TDS` need to be provided in the derived class. -\sa `Triangulation_ds_vertex` -\sa `Triangulation_data_structure>` +\sa `Triangulation_ds_vertex` +\sa `Triangulation_data_structure` */ -template< typename TriangulationDataStructure, typename TriangulationDSFullCellStoragePolicy > +template< typename TriangulationDataStructure_, typename TriangulationDSFullCellStoragePolicy > class Triangulation_ds_full_cell { public: diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation_ds_vertex.h b/Triangulation/doc/Triangulation/CGAL/Triangulation_ds_vertex.h index 8b576c17f46..7e06a55d2ab 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation_ds_vertex.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation_ds_vertex.h @@ -5,7 +5,7 @@ namespace CGAL { \ingroup PkgTriangulationsVertexCellClasses The class `Triangulation_ds_vertex` serves as the default vertex template parameter in the -class `Triangulation_data_structure`. +class `Triangulation_data_structure`. This class does not contain any geometric information but only combinatorial (adjacency) information. Thus, if the `Triangulation_data_structure` is @@ -20,7 +20,7 @@ example). Parameters -------------- -The template parameter `TriangulationDataStructure` must be a model of the +The template parameter `TriangulationDataStructure_` must be a model of the `TriangulationDataStructure` concept. \cgalModels ::TriangulationDSVertex @@ -31,11 +31,11 @@ Rebind mechanism In case of derivation from that class, the nested class `Rebind_TDS` need to be provided in the derived class. -\sa `Triangulation_ds_full_cell` -\sa `Triangulation_data_structure>` +\sa `Triangulation_ds_full_cell` +\sa `Triangulation_data_structure` */ -template< typename TriangulationDataStructure > +template< typename TriangulationDataStructure_ > class Triangulation_ds_vertex { public: diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation_face.h b/Triangulation/doc/Triangulation/CGAL/Triangulation_face.h index f62cebd0cc7..cdf39717c2d 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation_face.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation_face.h @@ -8,7 +8,7 @@ A `Triangulation_face` is a model of the concept `TriangulationDSFace`. Parameters -------------- -Parameter `TriangulationDataStructure` must be a model of the concept +Parameter `TriangulationDataStructure_` must be a model of the concept `TriangulationDataStructure`. Actually, `Triangulation_face` needs only that this concept defines the types `Full_cell_handle`, @@ -21,7 +21,7 @@ Actually, `Triangulation_face` needs only that this concept defines the types \sa `TriangulationDataStructure` */ -template< typename TriangulationDataStructure > +template< typename TriangulationDataStructure_ > class Triangulation_face { }; /* end Triangulation_face */ diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation_full_cell.h b/Triangulation/doc/Triangulation/CGAL/Triangulation_full_cell.h index 23d4664675b..9e4227c959a 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation_full_cell.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation_full_cell.h @@ -6,7 +6,7 @@ namespace CGAL { The class `Triangulation_full_cell` is a model of the concept `TriangulationFullCell`. It is used by default for representing full cells in the class -`Triangulation`. +`Triangulation`. A `Triangulation_full_cell` stores handles to the vertices of the cell as well as handles to its adjacent cells. @@ -14,9 +14,9 @@ to its adjacent cells. Parameters -------------- -`TriangulationTraits` must be a model of the concept `TriangulationTraits`. It +`TriangulationTraits_` must be a model of the concept `TriangulationTraits`. It provides geometric types and predicates for use in the -`Triangulation` class. +`Triangulation` class. `Data` is an optional type of data to be stored in the full cell class. The class template `Triangulation_full_cell` accepts that no second parameter be specified. In @@ -33,13 +33,13 @@ cases, `TriangulationDSFullCell_` defaults to `CGAL::Triangulation_ds_full_cell< `Triangulation_full_cell` provides the following types, constructors and methods: -\sa `Triangulation_vertex` -\sa `Triangulation_data_structure` -\sa `Triangulation` -\sa `Delaunay_triangulation` +\sa `Triangulation_vertex` +\sa `Triangulation_data_structure` +\sa `Triangulation` +\sa `Delaunay_triangulation` */ -template< typename TriangulationTraits, typename Data, typename TriangulationDSFullCell_ > +template< typename TriangulationTraits_, typename Data, typename TriangulationDSFullCell_ > class Triangulation_full_cell : public TriangulationDSFullCell_ { public: diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h b/Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h index 7ac94fc227e..cc74ea332e8 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h @@ -6,16 +6,16 @@ namespace CGAL { The class `Triangulation_vertex` is a model of the concept `TriangulationVertex`. It is used by default for representing vertices in the class -`Triangulation`. +`Triangulation`. A `Triangulation_vertex` stores a point and an incident full cell. Parameters -------------- -`TriangulationTraits` must be a model of the concept `TriangulationTraits`. It +`TriangulationTraits_` must be a model of the concept `TriangulationTraits`. It provides geometric types and predicates for use in the -`Triangulation` class. It is of interest here for its +`Triangulation` class. It is of interest here for its declaration of the `Point` type. `Data` is an optional type of data to be stored in the vertex class. The @@ -25,22 +25,22 @@ this case, `Data` defaults to `CGAL::No_vertex_data`. third parameter. Parameter -`TriangulationDSVertex` must be a model of the concept `TriangulationDSVertex`. The +`TriangulationDSVertex_` must be a model of the concept `TriangulationDSVertex`. The class template `Triangulation_vertex` accepts that no third parameter be specified. It also accepts the tag `CGAL::Default` as third parameter. In both cases, -`TriangulationDSVertex` defaults to `CGAL::Triangulation_ds_vertex<>`. +`TriangulationDSVertex_` defaults to `CGAL::Triangulation_ds_vertex<>`. \cgalModels ::TriangulationVertex Additionally, the class `Triangulation_vertex` provides the following types, constructors and methods: -\sa `Triangulation_full_cell` -\sa `Triangulation_data_structure` -\sa `Triangulation` -\sa `Delaunay_triangulation` +\sa `Triangulation_full_cell` +\sa `Triangulation_data_structure` +\sa `Triangulation` +\sa `Delaunay_triangulation` */ -template< typename TriangulationTraits, typename Data, typename TriangulationDSVertex > -class Triangulation_vertex : public TriangulationDSVertex { +template< typename TriangulationTraits_, typename Data, typename TriangulationDSVertex_ > +class Triangulation_vertex : public TriangulationDSVertex_ { public: /// \name Types diff --git a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h index 6211c847176..d00211362a9 100644 --- a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h @@ -5,7 +5,7 @@ This concept describes the geometric types and predicates required to build a Delaunay triangulation. It corresponds to the first template parameter of the class -`CGAL::Delaunay_triangulation`. +`CGAL::Delaunay_triangulation`. \cgalRefines ::TriangulationTraits. diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 31fc0d13a70..8a96a158a27 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -5,7 +5,7 @@ This concept describes the geometric types and predicates required to build a regular triangulation. It corresponds to the first template parameter of the class -`CGAL::Regular_triangulation`. +`CGAL::Regular_triangulation`. \cgalRefines ::TriangulationTraits. diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFace.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFace.h index d00669714db..9157aa654c2 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFace.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFace.h @@ -15,7 +15,7 @@ The dimension of a face is implicitely set when `TriangulationDSFace::set_index` is called two times to set the first two vertices (`i = 0` and `i = 1`), then the dimension is 1. -\cgalHasModel `CGAL::Triangulation_face` +\cgalHasModel `CGAL::Triangulation_face` \sa `TriangulationDSFullCell` \sa `TriangulationDSVertex` diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h index b5d39ced7a0..9940246c03d 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h @@ -36,8 +36,8 @@ of `CGAL::Triangulation_data_structure::Vertex`. \cgalRefines `TriangulationDataStructure::FullCell` -\cgalHasModel CGAL::Triangulation_ds_full_cell -\cgalHasModel CGAL::Triangulation_full_cell +\cgalHasModel CGAL::Triangulation_ds_full_cell +\cgalHasModel CGAL::Triangulation_full_cell \sa `TriangulationDSVertex` \sa `TriangulationDSFace` diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h index 37859785f99..20adc80ec3b 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h @@ -37,7 +37,7 @@ of `CGAL::Triangulation_data_structure::Vertex`. \cgalRefines `TriangulationDataStructure::Vertex` \cgalHasModel CGAL::Triangulation_ds_vertex -\cgalHasModel CGAL::Triangulation_vertex +\cgalHasModel CGAL::Triangulation_vertex \sa `TriangulationDSFullCell` \sa `TriangulationDSFace` diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDataStructure.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDataStructure.h index e94d15d7806..ca23b142f0e 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDataStructure.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDataStructure.h @@ -26,8 +26,8 @@ which is also the unique vertex and the unique full cell in the `TriangulationDataStructure`. In a geometric realization of the `TriangulationDataStructure` (e.g., in a -`Triangulation` or a -`Delaunay_triangulation`), this vertex +`Triangulation` or a +`Delaunay_triangulation`), this vertex corresponds to the vertex at infinity.
    0
    This corresponds to two vertices, each incident to one \f$ 0\f$-face; @@ -70,7 +70,7 @@ The classes `Vertex` and `Full_cell` have to provide the relevant I/O operators (possibly empty). -\cgalHasModel `CGAL::Triangulation_data_structure` +\cgalHasModel `CGAL::Triangulation_data_structure` \sa `TriangulationDataStructure::Vertex` \sa `TriangulationDataStructure::FullCell` @@ -665,8 +665,8 @@ It sets requirements of combinatorial nature only, as geometry is not concerned here. In particular, we only require that the vertex holds a handle to a full cell incident to it in the triangulation. -\cgalHasModel `CGAL::Triangulation_ds_vertex` -\cgalHasModel `CGAL::Triangulation_vertex` +\cgalHasModel `CGAL::Triangulation_ds_vertex` +\cgalHasModel `CGAL::Triangulation_vertex` \sa `TriangulationDataStructure::FullCell` \sa `TriangulationDataStructure::Face` @@ -772,8 +772,8 @@ full cell as well as handles to the adjacent full cells. Two full cells are said to be adjacent when they share a facet. Adjacent full cells are called hereafter neighbors. -\cgalHasModel `CGAL::Triangulation_ds_full_cell` -\cgalHasModel `CGAL::Triangulation_full_cell` +\cgalHasModel `CGAL::Triangulation_ds_full_cell` +\cgalHasModel `CGAL::Triangulation_full_cell` \sa `TriangulationDataStructure::FullCell` \sa `TriangulationDataStructure::Face` diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationFullCell.h b/Triangulation/doc/Triangulation/Concepts/TriangulationFullCell.h index 52546222cfc..e4898a3a6ef 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationFullCell.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationFullCell.h @@ -4,17 +4,17 @@ \cgalConcept The concept `TriangulationFullCell` describes the requirements on the type used by the -class `Triangulation`, and its derived classes, to +class `Triangulation`, and its derived classes, to represent a full cell. \cgalRefines ::TriangulationDSFullCell We only list below the additional specific requirements of ::TriangulationFullCell. -\cgalHasModel CGAL::Triangulation_full_cell +\cgalHasModel CGAL::Triangulation_full_cell -\sa `Triangulation_full_cell` +\sa `Triangulation_full_cell` \sa `TriangulationVertex` -\sa `Triangulation` +\sa `Triangulation` */ diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h index 70dfd38cebd..71eb3a158d2 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h @@ -5,7 +5,7 @@ This concept describes the geometric types and predicates required to build a triangulation. It corresponds to the first template parameter of the class -`CGAL::Triangulation`. +`CGAL::Triangulation`. \cgalRefines `SpatialSortingTraits_d` diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationVertex.h b/Triangulation/doc/Triangulation/Concepts/TriangulationVertex.h index 2e8dc810407..ece6d243543 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationVertex.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationVertex.h @@ -4,7 +4,7 @@ \cgalConcept The concept `TriangulationVertex` describes the requirements on the type used by the -class `Triangulation`, and its derived classes, to +class `Triangulation`, and its derived classes, to represent a vertex. \cgalRefines ::TriangulationDSVertex @@ -12,7 +12,7 @@ We only list below the additional specific requirements of ::TriangulationVertex Compared to ::TriangulationDSVertex, the main difference is the addition of an association of the vertex with a geometric point. -\cgalHasModel CGAL::Triangulation_vertex +\cgalHasModel CGAL::Triangulation_vertex Input/Output -------------- @@ -20,9 +20,9 @@ Input/Output These operators can be used directly and are called by the I/O operator of class `Triangulation`. -\sa `Triangulation_vertex` +\sa `Triangulation_vertex` \sa `TriangulationFullCell` -\sa `Triangulation` +\sa `Triangulation` */ @@ -36,7 +36,7 @@ public: The type of the point stored in the vertex. It must be the same as the point type `TriangulationTraits::Point` (or its refined concepts) when the `TriangulationVertex` is used in the class -`Triangulation` (or its derived classes). +`Triangulation` (or its derived classes). */ typedef unspecified_type Point; diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 8a343c54ea2..af840a8049f 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -95,17 +95,17 @@ The latter two concepts are also abbreviated respectively as `TrVertex` and `TrF ## Triangulation Data Structure ## - `CGAL::Triangulation_data_structure` -- `CGAL::Triangulation_ds_vertex` -- `CGAL::Triangulation_ds_full_cell` -- `CGAL::Triangulation_face` +- `CGAL::Triangulation_ds_vertex` +- `CGAL::Triangulation_ds_full_cell` +- `CGAL::Triangulation_face` ## (Geometric) Triangulations ## -- `CGAL::Triangulation` -- `CGAL::Delaunay_triangulation` -- `CGAL::Regular_triangulation` -- `CGAL::Triangulation_vertex` -- `CGAL::Triangulation_full_cell` +- `CGAL::Triangulation` +- `CGAL::Delaunay_triangulation` +- `CGAL::Regular_triangulation` +- `CGAL::Triangulation_vertex` +- `CGAL::Triangulation_full_cell` ## Enums ## diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 3d1c3137122..b75950c9172 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -83,21 +83,21 @@ models an abstract triangulation: vertices in this class are not embedded in Euclidean space but are only of combinatorial nature. -The class `CGAL::Triangulation` +The class `CGAL::Triangulation` describes an embedded triangulation that has as vertices a given set of points. Methods are provided for the insertion of points in the triangulation, the traversal of various elements of the triangulation, as well as the location of a query point inside the triangulation. The triangulation covers the convex hull of the set of points. -The class `CGAL::Delaunay_triangulation` +The class `CGAL::Delaunay_triangulation` builds the Delaunay triangulation of a set of points. In a Delaunay triangulation, each face has the so-called Delaunay or empty-ball property: there exists a circumscribing ball whose interior does not contain any vertex of the triangulation. -The class `CGAL::Regular_triangulation` +The class `CGAL::Regular_triangulation` builds the regular triangulation -- also known as weighted Delaunay triangulation -- of a set of points. A detailed definition of such a triangulation is available in section @@ -192,7 +192,7 @@ indices alongside the references to the vertices and neighbors in a full cell. This improves speed a little, but requires more memory. \cgalAdvanced \cgal provides the class template -`Triangulation_ds_full_cell` for representing full cells in a triangulation. Its second template parameter is used to specify wether or not the mirror indices should be kept in memory or computed @@ -228,10 +228,10 @@ constructor (see `TriangulationDataStructure`). The `TriangulationDSVertex_` and `TriangulationDSFullCell_` parameters to the class template must be models of the concepts `TriangulationDSVertex` and `TriangulationDSFullCell` respectively. \cgal provides models for these -concepts: `Triangulation_ds_vertex` and -`Triangulation_ds_full_cell`, which, as one -can see, take the `TriangulationDataStructure` as a template parameter in order to get access to -some nested types in `TriangulationDataStructure`. +concepts: `Triangulation_ds_vertex` and +`Triangulation_ds_full_cell`, which, as one +can see, take the triangulation data structure as a template parameter in order to get access to +some nested types in `TriangulationDataStructure_`. The default values are `CGAL::Triangulation_ds_vertex` and `CGAL::Triangulation_ds_full_cell` @@ -288,7 +288,7 @@ Barycentric subdivision in dimension \f$ d=2\f$. \section TriangulationSecTriangulations Triangulations -The class `CGAL::Triangulation` +The class `CGAL::Triangulation` maintains a triangulation embedded in Euclidean space. The triangulation covers the convex hull of the input points (the embedded vertices of the triangulation). @@ -318,11 +318,11 @@ the hyperplane supported by its finite facet where there is no other point. ## Implementation ## -The class `CGAL::Triangulation` +The class `CGAL::Triangulation` stores a model of the concept `TriangulationDataStructure` that is instantiated with a vertex type that stores a point. -The template parameter `TriangulationTraits` must be a model of the concept +The template parameter `TriangulationTraits_` must be a model of the concept `TriangulationTraits`, which provides the point type as well as various geometric predicates used by the `Triangulation` class. @@ -333,7 +333,7 @@ given as arguments to the predicates. This type is either In any case, the dimension of the traits must match the maximal dimension of the triangulation data structure. -The template parameter `TriangulationDataStructure` must be a model of the concept +The template parameter `TriangulationDataStructure_` must be a model of the concept `TriangulationDataStructure` which provides the triangulation data structure as described in the previous section. @@ -385,8 +385,8 @@ visits only the infinite full cells but stores handles to them into the \section TriangulationSecDT Delaunay Triangulations -The class `CGAL::Delaunay_triangulation` derives from -`CGAL::Triangulation` +The class `CGAL::Delaunay_triangulation` derives from +`CGAL::Triangulation` and represents Delaunay triangulations. A circumscribing ball of a simplex is a ball @@ -420,12 +420,12 @@ than inserting the same points one by one. ## Implementation ## -The class `CGAL::Delaunay_triangulation` derives from -`CGAL::Triangulation`. It thus stores a model of +The class `CGAL::Delaunay_triangulation` derives from +`CGAL::Triangulation`. It thus stores a model of the concept `TriangulationDataStructure`, which is instantiated with a vertex type that stores a geometric point and allows its retrieval. -The template parameter `DelaunayTriangulationTraits` must be a model of the concept +The template parameter `DelaunayTriangulationTraits_` must be a model of the concept `DelaunayTriangulationTraits` which provides the geometric `Point` type as well as various geometric predicates used by the `Delaunay_triangulation` class. The concept `DelaunayTriangulationTraits` refines the concept @@ -447,8 +447,8 @@ retaining an efficient update of the Delaunay triangulation. \section TriangulationSecRT Regular Triangulations -The class `CGAL::Regular_triangulation` derives from -`CGAL::Triangulation` +The class `CGAL::Regular_triangulation` derives from +`CGAL::Triangulation` and represents regular triangulations. Regular triangulations are similar to Delaunay triangulations, but @@ -487,12 +487,12 @@ than inserting the same points one by one. ## Implementation ## -The class `CGAL::Regular_triangulation` derives from -`CGAL::Triangulation`. It thus stores a model of -the concept `TriangulationDataStructure` which is instantiated with a vertex +The class `CGAL::Regular_triangulation` derives from +`CGAL::Triangulation`. It thus stores a model of +the concept `TriangulationDataStructure_` which is instantiated with a vertex type that stores a weighted point and allows its retrieval. -The template parameter `RegularTriangulationTraits` must be a model of the concept +The template parameter `RegularTriangulationTraits_` must be a model of the concept `RegularTriangulationTraits`. It must provide the `%Weighted_point` type as well as various geometric predicates used by the `Regular_triangulation` class. From 8cb1479d11576fc6df1e7dde1418abf62c5c154b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 May 2016 18:38:02 +0200 Subject: [PATCH 424/487] Fix example --- Triangulation/examples/Triangulation/regular_triangulation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Triangulation/examples/Triangulation/regular_triangulation.cpp b/Triangulation/examples/Triangulation/regular_triangulation.cpp index a8a917db17e..bae40c7711a 100644 --- a/Triangulation/examples/Triangulation/regular_triangulation.cpp +++ b/Triangulation/examples/Triangulation/regular_triangulation.cpp @@ -10,7 +10,8 @@ const int D = 5; // Dimension const int N = 100; // Number of points typedef CGAL::Epick_d< CGAL::Dimension_tag > K; -typedef CGAL::Regular_triangulation T; +typedef CGAL::Regular_triangulation< + CGAL::Regular_triangulation_euclidean_traits > T; typedef T::Bare_point Bare_point; typedef T::Weighted_point Weighted_point; From 5f47151eaf0e087b0595c8cce365a73b86a24db2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 May 2016 18:40:07 +0200 Subject: [PATCH 425/487] Fix too-long line --- Triangulation/test/Triangulation/test_regular.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index a4dc13260c8..489f6b65805 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -107,7 +107,8 @@ void go(const int N) { //typedef CGAL::Epick_d FK; typedef CGAL::Epick_d > FK; - typedef CGAL::Regular_triangulation > Triangulation; + typedef CGAL::Regular_triangulation< + CGAL::Regular_triangulation_euclidean_traits > Triangulation; //test(D, "dynamic", N); test(D, "static", N); } From f9c4148d4cec5b56a533cd699aaa31654b1dfb43 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 May 2016 10:34:47 +0200 Subject: [PATCH 426/487] Small fixes --- Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h | 5 +---- .../doc/Triangulation/Concepts/RegularTriangulationTraits.h | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 7713b0972d2..ea9cb9b96f7 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -16,9 +16,6 @@ section in the user manual for what reasonable means. A comprehensive definition of regular triangulations is available in the User Manual. -Parameters --------------- - \tparam RegularTriangulationTraits_ is the geometric traits class that provides the geometric types and predicates needed by regular triangulations. `RegularTriangulationTraits_` must be a model of the concept @@ -73,7 +70,7 @@ Regular_triangulation(const int dim, const Geom_traits gt = Geom_traits()); /// @} -/// \name Point insertion +/// \name Point Insertion /// @{ /*! diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 8a96a158a27..242aaf80014 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -7,7 +7,7 @@ This concept describes the geometric types and predicates required to build a regular triangulation. It corresponds to the first template parameter of the class `CGAL::Regular_triangulation`. -\cgalRefines ::TriangulationTraits. +\cgalRefines TriangulationTraits. \cgalHasModel `CGAL::Epick_d` */ From 258034c5ed4a0999a18f398d2494da4cc0e75d1c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 May 2016 10:59:40 +0200 Subject: [PATCH 427/487] Mention hidden points. --- Triangulation/doc/Triangulation/Triangulation.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 4c8d50ab9b9..0cb24b96167 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -477,6 +477,9 @@ called the power sphere. A sphere \f$ {z}^{(w)}\f$ is said to be A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres of all simplices are regular. +Note that as a result, some points can be hidden and do not result in vertices +in the triangulation. + Regular triangulations support insertion of weighted points, and location of a query point inside the triangulation. Note that inserting a large set of points at once is much faster From 9add88a784a3de81083a3e6d1fca4a554063d5ae Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 May 2016 11:17:02 +0200 Subject: [PATCH 428/487] Doc fixes (Monique's review) --- Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h | 2 +- Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h | 2 +- .../doc/Triangulation/Concepts/DelaunayTriangulationTraits.h | 2 +- .../doc/Triangulation/Concepts/RegularTriangulationTraits.h | 2 +- Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h index 4d7f952a9af..885edaade3a 100644 --- a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h @@ -7,7 +7,7 @@ namespace CGAL { This class is used to maintain the Delaunay triangulation of a set of points in \f$ \mathbb{R}^D \f$. It permits point insertion and -removal. The dimension \f$ D\f$ can be specified at compile-time or +removal. The maximal dimension \f$ D\f$ can be specified at compile-time or run-time. It should be kept reasonably small, see the performance section in the user manual for what reasonable means. diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index ea9cb9b96f7..14c734d22d7 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -7,7 +7,7 @@ namespace CGAL { This class is used to maintain the regular triangulation -- also known as weighted Delaunay triangulation -- of a set of weighted points in \f$ \mathbb{R}^D \f$. -The dimension \f$ D\f$ can be specified at compile-time or +The maximal dimension \f$ D\f$ can be specified at compile-time or run-time. It should be kept reasonably small -- see the performance section in the user manual for what reasonable means. diff --git a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h index 3f1da9f6aa9..f5d6345384c 100644 --- a/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/DelaunayTriangulationTraits.h @@ -71,7 +71,7 @@ typedef unspecified_type In_flat_side_of_oriented_sphere_d; /*! The default constructor (optional). -This is not required if an instance of the traits will be provided +This is not required when an instance of the traits is provided to the constructor of `CGAL::Delaunay_triangulation`. */ DelaunayTriangulationTraits(); diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 242aaf80014..8a2c3e6a088 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -94,7 +94,7 @@ typedef unspecified_type In_flat_power_test_d; /*! The default constructor (optional). -This is not required if an instance of the traits will be provided +This is not required when an instance of the traits is provided to the constructor of `CGAL::Regular_triangulation`. */ RegularTriangulationTraits(); diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h index 71eb3a158d2..8d997b84e40 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h @@ -138,7 +138,7 @@ typedef unspecified_type Compare_lexicographically_d; /*! The default constructor (optional). -This is not required if an instance of the traits will be provided +This is not required when an instance of the traits is provided to the constructor of `CGAL::Triangulation`. */ TriangulationTraits(); From 5ddfba30fd2853ff1989028579df0ae713604cd4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 May 2016 15:10:00 +0200 Subject: [PATCH 429/487] Remove useless and undocumented "circumcenter()" member function --- .../Concepts/RegularTriangulationTraits.h | 14 +++++++------- .../include/CGAL/Triangulation_full_cell.h | 16 ---------------- .../test/Triangulation/test_triangulation.cpp | 1 - 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 8a2c3e6a088..6d5eb78afcb 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -9,7 +9,7 @@ a regular triangulation. It corresponds to the first template parameter of the c \cgalRefines TriangulationTraits. -\cgalHasModel `CGAL::Epick_d` +\cgalHasModel `CGAL::Regular_triangulation_euclidean_traits` */ class RegularTriangulationTraits { public: @@ -18,14 +18,14 @@ public: /// @{ /*! -A number type that is a model for `RingNumberType`. +A number type that is a model for `FieldNumberType`. */ -typedef unspecified_type RT; +typedef unspecified_type FT; /*! The weighted point type. */ -typedef unspecified_type Weighted_point_d; +typedef unspecified_type Weighted_point; /*! A function object that must provide the operator @@ -36,14 +36,14 @@ typedef unspecified_type Point_drop_weight_d; /*! A function object that must provide the operator -`RT operator()(const Weighted_point & wp)`, returning +`FT operator()(const Weighted_point & wp)`, returning the weight of `wp`. */ typedef unspecified_type Point_weight_d; /*! A predicate object that must provide the templated operator -`template Oriented_side operator()(ForwardIterator start, ForwardIterator end, const Weighted_point_d & p)`. +`template Oriented_side operator()(ForwardIterator start, ForwardIterator end, const Weighted_point & p)`. Let \f$ S \f$ be the power sphere of the weighted points in range `[start,end)`. The operator returns: - `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to @@ -64,7 +64,7 @@ typedef unspecified_type Power_test_d; /*! A predicate object that must provide the templated operator -`template Oriented_side operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end, const Weighted_point_d & p)`. +`template Oriented_side operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end, const Weighted_point & p)`. The points in range `[start,end)` and `p` are supposed to belong to the lower-dimensional flat whose orientation is given by `orient`. diff --git a/Triangulation/include/CGAL/Triangulation_full_cell.h b/Triangulation/include/CGAL/Triangulation_full_cell.h index 1a09747858f..a0c5246fa14 100644 --- a/Triangulation/include/CGAL/Triangulation_full_cell.h +++ b/Triangulation/include/CGAL/Triangulation_full_cell.h @@ -66,22 +66,6 @@ public: Triangulation_full_cell(const Self & s) : Base(s), data_(s.data_) {} - Point circumcenter() const - { - TriangulationTraits pct; - Vertex_handle_const_iterator vhit = vertices_begin(); - while( vhit != vertices_end() ) - { - if( *vhit == Vertex_const_handle() ) - { - CGAL_warning_msg(false, "too few points; can not compute circumcenter."); - return Point(); - } - ++vhit; - } - return pct.center_of_sphere_d_object()(points_begin(), points_end()); - } - const Data & data() const { return data_; diff --git a/Triangulation/test/Triangulation/test_triangulation.cpp b/Triangulation/test/Triangulation/test_triangulation.cpp index 09c7698c5db..4e225333054 100644 --- a/Triangulation/test/Triangulation/test_triangulation.cpp +++ b/Triangulation/test/Triangulation/test_triangulation.cpp @@ -53,7 +53,6 @@ void test(const int d, const string & type, int N) Finite_full_cell_const_iterator fsit = tri.finite_full_cells_begin(); while( fsit != tri.finite_full_cells_end() ) { - fsit->circumcenter(); ++fsit, ++nbfs; } cerr << nbfs << " + "; From 81e2e215fa9340c10e051a01a4e4601dcdd541c9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 May 2016 18:00:16 +0200 Subject: [PATCH 430/487] Monique's review, incl. renaming of power_test + better handling of the insertion of points at the same position (incl. test) --- .../include/CGAL/NewKernel_d/Coaffine.h | 6 +- .../CGAL/NewKernel_d/Kernel_d_interface.h | 8 +- .../CGAL/NewKernel_d/Types/Weighted_point.h | 16 +- .../NewKernel_d/function_objects_cartesian.h | 8 +- .../include/CGAL/NewKernel_d/functor_tags.h | 8 +- NewKernel_d/test/NewKernel_d/Epick_d.cpp | 8 +- .../CGAL/Delaunay_triangulation.h | 8 - .../CGAL/Regular_triangulation.h | 60 ++++--- .../doc/Triangulation/CGAL/Triangulation.h | 35 +--- .../Concepts/RegularTriangulationTraits.h | 23 ++- .../doc/Triangulation/Triangulation.txt | 2 +- .../include/CGAL/Delaunay_triangulation.h | 2 +- .../include/CGAL/Regular_triangulation.h | 79 ++++---- .../Regular_triangulation_euclidean_traits.h | 19 +- .../test/Triangulation/test_regular.cpp | 168 +++++++++++++++++- 15 files changed, 315 insertions(+), 135 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h index 62ad90afa9c..43015d24fef 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Coaffine.h @@ -269,8 +269,8 @@ template struct In_flat_side_of_oriented_sphere : private Store_kernel } }; -template struct In_flat_power_test_raw : private Store_kernel { - CGAL_FUNCTOR_INIT_STORE(In_flat_power_test_raw) +template struct In_flat_power_side_of_power_sphere_raw : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(In_flat_power_side_of_power_sphere_raw) typedef R_ R; typedef typename Get_type::type FT; typedef typename Get_type::type Point; @@ -323,7 +323,7 @@ template struct In_flat_power_test_raw : private Store_kernel { CGAL_KD_DEFAULT_TYPE(Flat_orientation_tag,(CGAL::CartesianDKernelFunctors::Flat_orientation),(),()); CGAL_KD_DEFAULT_FUNCTOR(In_flat_orientation_tag,(CartesianDKernelFunctors::In_flat_orientation),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); CGAL_KD_DEFAULT_FUNCTOR(In_flat_side_of_oriented_sphere_tag,(CartesianDKernelFunctors::In_flat_side_of_oriented_sphere),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); -CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_test_raw_tag,(CartesianDKernelFunctors::In_flat_power_test_raw),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); +CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_raw_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere_raw),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); CGAL_KD_DEFAULT_FUNCTOR(Construct_flat_orientation_tag,(CartesianDKernelFunctors::Construct_flat_orientation),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag,In_flat_orientation_tag)); CGAL_KD_DEFAULT_FUNCTOR(Contained_in_affine_hull_tag,(CartesianDKernelFunctors::Contained_in_affine_hull),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); } diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index d7fdd545000..22e0272d5ad 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -65,12 +65,12 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Less_coordinate_d; typedef typename Get_functor::type Point_dimension_d; typedef typename Get_functor::type Side_of_oriented_sphere_d; - typedef typename Get_functor::type Power_test_d; + typedef typename Get_functor::type Power_side_of_power_sphere_d; typedef typename Get_functor::type Contained_in_affine_hull_d; typedef typename Get_functor::type Construct_flat_orientation_d; typedef typename Get_functor::type In_flat_orientation_d; typedef typename Get_functor::type In_flat_side_of_oriented_sphere_d; - typedef typename Get_functor::type In_flat_power_test_d; + typedef typename Get_functor::type In_flat_power_side_of_power_sphere_d; typedef typename Get_functor::type Point_to_vector_d; typedef typename Get_functor::type Vector_to_point_d; typedef typename Get_functor::type Scaled_vector_d; @@ -187,7 +187,7 @@ template struct Kernel_d_interface : public Base_ { Point_dimension_d point_dimension_d_object()const{ return Point_dimension_d(*this); } Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); } Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } - Power_test_d power_test_d_object()const{ return Power_test_d(*this); } + Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); } Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); } Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); } @@ -195,7 +195,7 @@ template struct Kernel_d_interface : public Base_ { Construct_flat_orientation_d construct_flat_orientation_d_object()const{ return Construct_flat_orientation_d(*this); } In_flat_orientation_d in_flat_orientation_d_object()const{ return In_flat_orientation_d(*this); } In_flat_side_of_oriented_sphere_d in_flat_side_of_oriented_sphere_d_object()const{ return In_flat_side_of_oriented_sphere_d(*this); } - In_flat_power_test_d in_flat_power_test_d_object()const{ return In_flat_power_test_d(*this); } + In_flat_power_side_of_power_sphere_d in_flat_power_side_of_power_sphere_d_object()const{ return In_flat_power_side_of_power_sphere_d(*this); } Point_to_vector_d point_to_vector_d_object()const{ return Point_to_vector_d(*this); } Vector_to_point_d vector_to_point_d_object()const{ return Vector_to_point_d(*this); } Scaled_vector_d scaled_vector_d_object()const{ return Scaled_vector_d(*this); } diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 32e8b586b58..4896d40e882 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -75,14 +75,14 @@ template struct Point_weight { } }; -template struct Power_test : private Store_kernel { - CGAL_FUNCTOR_INIT_STORE(Power_test) +template struct Power_side_of_power_sphere : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere) typedef R_ R; typedef typename Get_type::type result_type; template result_type operator()(Iter const& f, Iter const& e, Pt const& p0) const { - typename Get_functor::type ptr(this->kernel()); + typename Get_functor::type ptr(this->kernel()); typename Get_functor::type pdw(this->kernel()); typename Get_functor::type pw(this->kernel()); return ptr ( @@ -94,14 +94,14 @@ template struct Power_test : private Store_kernel { } }; -template struct In_flat_power_test : private Store_kernel { - CGAL_FUNCTOR_INIT_STORE(In_flat_power_test) +template struct In_flat_power_side_of_power_sphere : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(In_flat_power_side_of_power_sphere) typedef R_ R; typedef typename Get_type::type result_type; template result_type operator()(Fo const& fo, Iter const& f, Iter const& e, Pt const& p0) const { - typename Get_functor::type ptr(this->kernel()); + typename Get_functor::type ptr(this->kernel()); typename Get_functor::type pdw(this->kernel()); typename Get_functor::type pw(this->kernel()); return ptr ( @@ -119,7 +119,7 @@ CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::KerD::Weighted_point),(Point_t CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_drop_weight),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight),(Weighted_point_tag,Point_tag),()); -CGAL_KD_DEFAULT_FUNCTOR(Power_test_tag,(CartesianDKernelFunctors::Power_test),(Weighted_point_tag),(Power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); -CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_test_tag,(CartesianDKernelFunctors::In_flat_power_test),(Weighted_point_tag),(In_flat_power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere),(Weighted_point_tag),(Power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere),(Weighted_point_tag),(In_flat_power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag)); } // namespace CGAL #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h index 674b2f0260a..5a132ad295e 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h @@ -555,8 +555,8 @@ template struct Orientation : private Store_kernel { #endif namespace CartesianDKernelFunctors { -template struct Power_test_raw : private Store_kernel { - CGAL_FUNCTOR_INIT_STORE(Power_test_raw) +template struct Power_side_of_power_sphere_raw : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere_raw) typedef R_ R; typedef typename Get_type::type RT; typedef typename Get_type::type FT; @@ -605,9 +605,9 @@ template struct Power_test_raw : private Store_kernel { }; } -CGAL_KD_DEFAULT_FUNCTOR(Power_test_raw_tag,(CartesianDKernelFunctors::Power_test_raw),(Point_tag),(Point_dimension_tag,Squared_distance_to_origin_tag,Compute_point_cartesian_coordinate_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_raw_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere_raw),(Point_tag),(Point_dimension_tag,Squared_distance_to_origin_tag,Compute_point_cartesian_coordinate_tag)); -// TODO: make Side_of_oriented_sphere call Power_test_raw +// TODO: make Side_of_oriented_sphere call Power_side_of_power_sphere_raw namespace CartesianDKernelFunctors { template struct Side_of_oriented_sphere : private Store_kernel { CGAL_FUNCTOR_INIT_STORE(Side_of_oriented_sphere) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index f23239ce7b0..f0459906574 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -309,10 +309,10 @@ namespace CGAL { CGAL_DECL_PREDICATE(Affinely_independent); CGAL_DECL_PREDICATE(Contained_in_linear_hull); CGAL_DECL_PREDICATE(Contained_in_simplex); - CGAL_DECL_PREDICATE(Power_test_raw); - CGAL_DECL_PREDICATE(Power_test); - CGAL_DECL_PREDICATE(In_flat_power_test_raw); - CGAL_DECL_PREDICATE(In_flat_power_test); + CGAL_DECL_PREDICATE(Power_side_of_power_sphere_raw); + CGAL_DECL_PREDICATE(Power_side_of_power_sphere); + CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere_raw); + CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere); #undef CGAL_DECL_PREDICATE #define CGAL_DECL_MISC(X) struct X##_tag {}; \ diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index def19767d2e..264ba6fe4a6 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -598,13 +598,13 @@ void test3(){ typedef typename K1::Construct_weighted_point_d CWP; typedef typename K1::Point_drop_weight_d PDW; typedef typename K1::Point_weight_d PW; - typedef typename K1::Power_test_d PT; - typedef typename K1::In_flat_power_test_d IFPT; + typedef typename K1::Power_side_of_power_sphere_d PT; + typedef typename K1::In_flat_power_side_of_power_sphere_d IFPT; CWP cwp Kinit(construct_weighted_point_d_object); PDW pdw Kinit(point_drop_weight_d_object); PW pw Kinit(point_weight_d_object); - PT pt Kinit(power_test_d_object); - IFPT ifpt Kinit(in_flat_power_test_d_object); + PT pt Kinit(power_side_of_power_sphere_d_object); + IFPT ifpt Kinit(in_flat_power_side_of_power_sphere_d_object); WP wp; wp = cwp (x1, 2); WP xw6 = cwp (x6, 0); diff --git a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h index 885edaade3a..073654e453e 100644 --- a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h @@ -115,7 +115,6 @@ Same as above but uses a vertex as starting place for the search. Vertex_handle insert(const Point & p, Vertex_handle hint); /*! -\cgalAdvancedBegin Inserts the point `p` in the Delaunay triangulation and ensures that the empty-ball property is preserved. Returns a handle to the @@ -137,28 +136,23 @@ The parameters `lt`, `f`, `ft` and `c` must be consistent with the localization of point `p` in the Delaunay triangulation e.g. by a call to `Triangulation::locate(const Point &, Locate_type &, Face &, Vertex_handle) const`. -\cgalAdvancedEnd */ Vertex_handle insert(const Point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle c); /*! -\cgalAdvancedBegin Inserts the point `p` in the Delaunay triangulation. Returns a handle to the (possibly newly created) vertex at that position. \pre The point `p` must lie outside the affine hull of the Delaunay triangulation. This implies that `dt`.`current_dimension()` must be less than `dt`.`maximal_dimension()`. -\cgalAdvancedEnd */ Vertex_handle insert_outside_affine_hull(const Point & p); /*! -\cgalAdvancedBegin Inserts the point `p` in the Delaunay triangulation. Returns a handle to the (possibly newly created) vertex at that position. \pre The point `p` must be in conflict with the full cell `c`. -\cgalAdvancedEnd */ Vertex_handle insert_in_conflicting_cell(const Point & p, const Full_cell_handle c); @@ -177,7 +171,6 @@ bool is_in_conflict(const Point & p, Full_cell_const_handle c) const; /*! -\cgalAdvancedBegin Outputs handles to the full cells in conflict with point `p` into the `OutputIterator out`. The full cell `c` is used as a starting point for gathering the full cells in conflict with @@ -185,7 +178,6 @@ as a starting point for gathering the full cells in conflict with A facet `(cc,i)` on the boundary of the conflict zone with `cc` in conflict is returned. \pre `c` is in conflict with `p` and `dt`.`current_dimension()`\f$ \geq2\f$. -\cgalAdvancedEnd */ template< typename OutputIterator > Facet compute_conflict_zone(const Point & p, const Full_cell_handle c, diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 14c734d22d7..5cf79f1cf22 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -52,7 +52,7 @@ public: /*! A point in Euclidean space with an associated weight. */ -typedef RegularTriangulationTraits_::Weighted_point Weighted_point; +typedef RegularTriangulationTraits_::Weighted_point_d Weighted_point; /// @} @@ -63,8 +63,8 @@ typedef RegularTriangulationTraits_::Weighted_point Weighted_point; Instantiates a regular triangulation with one vertex (the vertex at infinity). See the description of the inherited nested type `Triangulation::Maximal_dimension` for an explanation of -the use of the parameter `dim`. The complex stores a copy of the geometric -traits `gt`. +the use of the parameter `dim`. The triangulation stores a copy of the +geometric traits `gt`. */ Regular_triangulation(const int dim, const Geom_traits gt = Geom_traits()); @@ -75,8 +75,22 @@ Regular_triangulation(const int dim, const Geom_traits gt = Geom_traits()); /*! Inserts weighted point `p` in the triangulation and returns the corresponding -vertex. Returns a handle to the (possibly newly created) vertex at that -position. +vertex. + +If this insertion creates a vertex, this vertex is returned. + +If `p` coincides with an existing vertex and has a greater weight, +then the existing weighted point becomes hidden and `p` replaces it as vertex +of the triangulation. + +If `p` coincides with an already existing vertex (both point and +weights being equal), then this vertex is returned and the triangulation +remains unchanged. + +Otherwise if `p` does not appear as a vertex of the triangulation, +then it is stored as a hidden point and this method returns the default +constructed handle. + Prior to the actual insertion, `p` is located in the triangulation; `hint` is used as a starting place for locating `p`. */ @@ -89,12 +103,10 @@ Same as above but uses a vertex as starting place for the search. Vertex_handle insert(const Weighted_point & p, Vertex_handle hint); /*! -\cgalAdvancedBegin -Inserts weighted point `p` in the triangulation and returns the corresponding -vertex. Similar to the above `insert()` function, but takes as additional +Inserts weighted point `p` in the triangulation. +Similar to the above `insert()` function, but takes as additional parameter the return values of a previous location query. See description of `Triangulation::locate()`. -\cgalAdvancedEnd */ Vertex_handle insert(const Weighted_point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle c); @@ -114,22 +126,32 @@ template< typename ForwardIterator > std::ptrdiff_t insert(ForwardIterator s, ForwardIterator e); /*! -\cgalAdvancedBegin Inserts the point `p` in the regular triangulation. Returns a handle to the -(possibly newly created) vertex at that position. +newly created vertex at that position. \pre The point `p` must lie outside the affine hull of the regular triangulation. This implies that -`rt`.`current_dimension()` must be less than `rt`.`maximal_dimension()`. -\cgalAdvancedEnd +`rt`.`current_dimension()` must be smaller than `rt`.`maximal_dimension()`. */ Vertex_handle insert_outside_affine_hull(const Weighted_point & p); /*! -\cgalAdvancedBegin -Inserts the point `p` in the regular triangulation. Returns a handle to the -(possibly newly created) vertex at that position. +Inserts the point `p` in the regular triangulation. + +If this insertion creates a vertex, this vertex is returned. + +If `p` coincides with an existing vertex and has a greater weight, +then the existing weighted point becomes hidden and `p` replaces it as vertex +of the triangulation. + +If `p` coincides with an already existing vertex (both point and +weights being equal), then this vertex is returned and the triangulation +remains unchanged. + +Otherwise if `p` does not appear as a vertex of the triangulation, +then it is stored as a hidden point and this method returns the default +constructed handle. + \pre The point `p` must be in conflict with the full cell `c`. -\cgalAdvancedEnd */ Vertex_handle insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle c); @@ -148,15 +170,13 @@ bool is_in_conflict(const Weighted_point & p, Full_cell_const_handle c) const; /*! -\cgalAdvancedBegin Outputs handles to the full cells in conflict with point `p` into the `OutputIterator out`. The full cell `c` is used as a starting point for gathering the full cells in conflict with `p`. A facet `(cc,i)` on the boundary of the conflict zone with `cc` in conflict is returned. -\pre `c` is in conflict with `p` and `rt`.`current_dimension()`\f$ \geq2\f$. -\cgalAdvancedEnd +\pre `c` is in conflict with `p` and `rt`.`current_dimension()`\f$ \geq 1\f$. */ template< typename OutputIterator > Facet compute_conflict_zone(const Weighted_point & p, const Full_cell_handle c, diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index 12bb78844cd..ce482d4b255 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -4,7 +4,7 @@ namespace CGAL { /*! \ingroup PkgTriangulationsTriangulationClasses -This class implements triangulations of point sets in dimensions \f$ d \f$. +This class implements triangulations of point sets in dimension \f$ d \f$. The triangulation covers the convex hull of the input points (the embedded vertices of the triangulation). @@ -72,8 +72,8 @@ This indicates whether the maximal dimension is static (i.e.\ if the type of `Maximal_dimension` is `CGAL::Dimension_tag`) or dynamic (i.e.\ if the type of `Maximal_dimension` is `CGAL::Dynamic_dimension_tag`). -In the latter case, the `dim` parameter passed to the class's constructor -is used. +In the latter case, the `dim` parameter passed to the constructor +of the class is used. */ typedef TriangulationTraits_::Dimension Maximal_dimension; @@ -201,19 +201,18 @@ iterator over finite facets typedef unspecified_type Finite_facet_iterator; /*! -Size type (an unsigned integral -type). +size type (an unsigned integral type) */ typedef TriangulationDataStructure_::size_type size_type; /*! -Difference -type (a signed integral type). +difference +type (a signed integral type) */ typedef TriangulationDataStructure_::difference_type difference_type; /*! -specifies which case occurs when locating a point in the triangulation. +used by `Triangulation` to specify which case occurs when locating a point in the triangulation */ enum Locate_type { ON_VERTEX=0, /*!< when the located point coincides with a vertex of the triangulation */ IN_FACE, /*!< when the point is in the interior of a face of dimension equal or less than `maximal_dimension()` - 2 */ @@ -248,15 +247,15 @@ Triangulation(const Triangulation & t2); /// @{ /*! -\cgalAdvancedBegin Returns a const reference to the underlying triangulation data structure. -\cgalAdvancedEnd */ const Triangulation_ds & tds() const; /*! +\cgalAdvancedBegin Returns a non-const reference to the underlying triangulation data structure. +\cgalAdvancedEnd */ Triangulation_ds & tds(); @@ -553,7 +552,6 @@ Same as above but uses a vertex `hint` as the starting place for the search. Vertex_handle insert(const Point p, Vertex_handle hint); /*! -\cgalAdvancedBegin Inserts point `p` into the triangulation and returns a handle to the `Vertex` at that position. The action taken depends on the value of `loc_type`: @@ -567,12 +565,10 @@ of `loc_type`, using the full cell `c`.
    This method is used internally by the other `insert()` methods. -\cgalAdvancedEnd */ Vertex_handle insert(const Point p, Locate_type loc_type, Face & f, Facet & ft, Full_cell_handle c); /*! -\cgalAdvancedBegin Removes the full cells in the range \f$ C=\f$`[s, e)`, inserts a vertex at position `p` and fills the hole by connecting each face of the boundary to `p`. @@ -582,62 +578,49 @@ defining full cell, `tr`.`full_cell(ft)` must lie inside \f$ C\f$. Handles to the newly created full cells are output in the `out` output iterator. \pre \f$C\f$ must be a topological ball, must contain `p` in its interior and must not contain any vertex of the triangulation. -\cgalAdvancedEnd */ template < typename ForwardIterator, typename OutputIterator > Vertex_handle insert_in_hole(const Point & p, ForwardIterator s, ForwardIterator e, const Facet & ft, OutputIterator out); /*! -\cgalAdvancedBegin Same as above, but the newly created full cells are not retrieved. -\cgalAdvancedEnd */ template < typename ForwardIterator > Vertex_handle insert_in_hole(const Point & p, ForwardIterator s, ForwardIterator e, const Facet & ft); /*! -\cgalAdvancedBegin Inserts point `p` in the triangulation. \pre `p` must lie in the relative interior of `f`. -\cgalAdvancedEnd */ Vertex_handle insert_in_face(const Point & p, const Face & f); /*! -\cgalAdvancedBegin Inserts point `p` in the triangulation. \pre `p` must lie in the relative interior of `ft`. -\cgalAdvancedEnd */ Vertex_handle insert_in_facet(const Point & p, const Facet & ft); /*! -\cgalAdvancedBegin Inserts point `p` in the triangulation. \pre `p` must lie in the interior of `c`. -\cgalAdvancedEnd */ Vertex_handle insert_in_full_cell(const Point & p, Full_cell_handle c); /*! -\cgalAdvancedBegin Inserts point `p` in the triangulation. \pre `p` must lie outside the convex hull of `tr`. The half-space defined by the infinite full cell `c` must contain `p`. -\cgalAdvancedEnd */ Vertex_handle insert_outside_convex_hull(const Point &, Full_cell_handle c); /*! -\cgalAdvancedBegin Inserts point `p` in the triangulation. \pre `p` must lie outside the affine hull of `tr`. -\cgalAdvancedEnd */ Vertex_handle insert_outside_affine_hull(const Point &); diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 6d5eb78afcb..1225347bf6b 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -25,25 +25,30 @@ typedef unspecified_type FT; /*! The weighted point type. */ -typedef unspecified_type Weighted_point; +typedef unspecified_type Weighted_point_d; + +/*! +The (un-weighted) point type. +*/ +typedef unspecified_type Bare_point_d; /*! A function object that must provide the operator -`Point_d operator()(const Weighted_point & wp)`, returning +`Point_d operator()(const Weighted_point_d & wp)`, returning `wp` without its weight. */ typedef unspecified_type Point_drop_weight_d; /*! A function object that must provide the operator -`FT operator()(const Weighted_point & wp)`, returning +`FT operator()(const Weighted_point_d & wp)`, returning the weight of `wp`. */ typedef unspecified_type Point_weight_d; /*! A predicate object that must provide the templated operator -`template Oriented_side operator()(ForwardIterator start, ForwardIterator end, const Weighted_point & p)`. +`template Oriented_side operator()(ForwardIterator start, ForwardIterator end, const Weighted_point_d & p)`. Let \f$ S \f$ be the power sphere of the weighted points in range `[start,end)`. The operator returns: - `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to @@ -60,11 +65,11 @@ The weighted points in range `[start,end)` must be affinely independent, i.e., the simplex must not be flat. */ -typedef unspecified_type Power_test_d; +typedef unspecified_type Power_side_of_power_sphere_d; /*! A predicate object that must provide the templated operator -`template Oriented_side operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end, const Weighted_point & p)`. +`template Oriented_side operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end, const Weighted_point_d & p)`. The points in range `[start,end)` and `p` are supposed to belong to the lower-dimensional flat whose orientation is given by `orient`. @@ -85,7 +90,7 @@ points used to construct `orient` (dimension of the flat). The points in range `[start,end)` must be affinely independent. `p` must be in the flat generated by these points. */ -typedef unspecified_type In_flat_power_test_d; +typedef unspecified_type In_flat_power_side_of_power_sphere_d; /// @} @@ -118,12 +123,12 @@ Point_weight_d point_weight_d_object() const; /*! */ -Power_test_d power_test_d_object() const; +Power_side_of_power_sphere_d power_side_of_power_sphere_d_object() const; /*! */ -In_flat_power_test_d in_flat_power_test_d_object() const; +In_flat_power_side_of_power_sphere_d in_flat_power_side_of_power_sphere_d_object() const; /// @} diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 0cb24b96167..b006eaf0647 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -495,7 +495,7 @@ the concept `TriangulationDataStructure_` which is instantiated with a vertex type that stores a weighted point and allows its retrieval. The template parameter `RegularTriangulationTraits_` must be a model of the concept -`RegularTriangulationTraits`. It must provide the `%Weighted_point` +`RegularTriangulationTraits`. It must provide the `%Weighted_point_d` type as well as various geometric predicates used by the `Regular_triangulation` class. The concept `RegularTriangulationTraits` refines the concept diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 258ee53ad42..bb53bc5c489 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -56,7 +56,7 @@ class Delaunay_triangulation public: // PUBLIC NESTED TYPES typedef DCTraits Geom_traits; - typedef typename Base::Triangulation_ds Triangulation_ds; + typedef typename Base::Triangulation_ds Triangulation_ds; typedef typename Base::Vertex Vertex; typedef typename Base::Full_cell Full_cell; diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 2a02b099b46..48bd49058ab 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -56,8 +56,9 @@ class Regular_triangulation typedef Regular_triangulation Self; typedef typename RTTraits::Orientation_d Orientation_d; - typedef typename RTTraits::Power_test_d Power_test_d; - typedef typename RTTraits::In_flat_power_test_d In_flat_power_test_d; + typedef typename RTTraits::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; + typedef typename RTTraits::In_flat_power_side_of_power_sphere_d + In_flat_power_side_of_power_sphere_d; typedef typename RTTraits::Flat_orientation_d Flat_orientation_d; typedef typename RTTraits::Construct_flat_orientation_d Construct_flat_orientation_d; @@ -72,8 +73,8 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Face Face; typedef Maximal_dimension_ Maximal_dimension; - typedef typename RTTraits::Bare_point Bare_point; - typedef typename RTTraits::Weighted_point Weighted_point; + typedef typename RTTraits::Bare_point_d Bare_point; + typedef typename RTTraits::Weighted_point_d Weighted_point; typedef typename Base::Point_const_iterator Point_const_iterator; typedef typename Base::Vertex_handle Vertex_handle; @@ -131,18 +132,18 @@ public: using Base::vertices_end; private: - //*** Power_test_in_flat_d *** CJTODO: better name? + // Wrapper - struct Power_test_in_flat_d + struct Power_side_of_power_sphere_for_non_maximal_dim_d { boost::optional* fop; Construct_flat_orientation_d cfo; - In_flat_power_test_d ifpt; + In_flat_power_side_of_power_sphere_d ifpt; - Power_test_in_flat_d( + Power_side_of_power_sphere_for_non_maximal_dim_d( boost::optional& x, Construct_flat_orientation_d const&y, - In_flat_power_test_d const&z) + In_flat_power_side_of_power_sphere_d const&z) : fop(&x), cfo(y), ifpt(z) {} template @@ -153,6 +154,7 @@ private: return ifpt(fop->get(),a,b,p); } }; + public: // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS @@ -180,12 +182,12 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS // Not Documented - Power_test_in_flat_d power_test_in_flat_predicate() const + Power_side_of_power_sphere_for_non_maximal_dim_d power_side_of_power_sphere_for_non_maximal_dim_predicate() const { - return Power_test_in_flat_d ( + return Power_side_of_power_sphere_for_non_maximal_dim_d ( flat_orientation_, geom_traits().construct_flat_orientation_d_object(), - geom_traits().in_flat_power_test_d_object() + geom_traits().in_flat_power_side_of_power_sphere_d_object() ); } @@ -302,7 +304,7 @@ public: bool is_in_conflict(const Weighted_point &, Full_cell_const_handle) const; template< class OrientationPredicate > - Oriented_side perturbed_power_test(const Weighted_point &, + Oriented_side perturbed_power_side_of_power_sphere(const Weighted_point &, Full_cell_const_handle, const OrientationPredicate &) const; template< typename OutputIterator > @@ -314,15 +316,15 @@ public: const Self & rt_; const Weighted_point & p_; OrientationPredicate ori_; - PowerTestPredicate power_test_; + PowerTestPredicate power_side_of_power_sphere_; int cur_dim_; public: Conflict_predicate( const Self & rt, const Weighted_point & p, const OrientationPredicate & ori, - const PowerTestPredicate & power_test) - : rt_(rt), p_(p), ori_(ori), power_test_(power_test), cur_dim_(rt.current_dimension()) {} + const PowerTestPredicate & power_side_of_power_sphere) + : rt_(rt), p_(p), ori_(ori), power_side_of_power_sphere_(power_side_of_power_sphere), cur_dim_(rt.current_dimension()) {} inline bool operator()(Full_cell_const_handle s) const @@ -330,13 +332,13 @@ public: bool ok; if( ! rt_.is_infinite(s) ) { - Oriented_side power_test = power_test_(rt_.points_begin(s), rt_.points_begin(s) + cur_dim_ + 1, p_); - if( ON_POSITIVE_SIDE == power_test ) + Oriented_side power_side_of_power_sphere = power_side_of_power_sphere_(rt_.points_begin(s), rt_.points_begin(s) + cur_dim_ + 1, p_); + if( ON_POSITIVE_SIDE == power_side_of_power_sphere ) ok = true; - else if( ON_NEGATIVE_SIDE == power_test ) + else if( ON_NEGATIVE_SIDE == power_side_of_power_sphere ) ok = false; else - ok = ON_POSITIVE_SIDE == rt_.perturbed_power_test(p_, s, ori_); + ok = ON_POSITIVE_SIDE == rt_.perturbed_power_side_of_power_sphere(p_, s, ori_); } else { @@ -380,6 +382,13 @@ public: bool is_valid(bool verbose = false, int level = 0) const; +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MISC + + std::size_t number_of_hidden_points() const + { + return m_hidden_points.size(); + } + private: template @@ -446,9 +455,9 @@ private: // Some internal types to shorten notation using typename Base::Coaffine_orientation_d; using Base::flat_orientation_; - typedef Conflict_predicate + typedef Conflict_predicate Conflict_pred_in_subspace; - typedef Conflict_predicate + typedef Conflict_predicate Conflict_pred_in_fullspace; typedef Conflict_traversal_predicate Conflict_traversal_pred_in_subspace; @@ -808,13 +817,21 @@ Regular_triangulation if (pw(p) == pw(v->point())) return v; // If dim == 0 and the new point has a bigger weight, - // we replace the point + // we just replace the point, and the former point gets hidden else if (current_dimension() == 0) { if (pw(p) > pw(v->point())) + { + m_hidden_points.push_back(v->point()); v->set_point(p); - else return v; + } + // Otherwise, the new point is hidden + else + { + m_hidden_points.push_back(p); + return Vertex_handle(); + } } // Otherwise, we apply the "normal" algorithm @@ -968,7 +985,7 @@ template< typename Traits, typename TDS > template< typename OrientationPred > Oriented_side Regular_triangulation -::perturbed_power_test(const Weighted_point & p, Full_cell_const_handle s, +::perturbed_power_side_of_power_sphere(const Weighted_point & p, Full_cell_const_handle s, const OrientationPred & ori) const { CGAL_precondition_msg( ! is_infinite(s), "full cell must be finite"); @@ -1033,13 +1050,13 @@ Regular_triangulation Conflict_pred_in_subspace c( *this, p, coaffine_orientation_predicate(), - power_test_in_flat_predicate()); + power_side_of_power_sphere_for_non_maximal_dim_predicate()); return c(s); } else { Orientation_d ori = geom_traits().orientation_d_object(); - Power_test_d side = geom_traits().power_test_d_object(); + Power_side_of_power_sphere_d side = geom_traits().power_side_of_power_sphere_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); return c(s); } @@ -1057,14 +1074,14 @@ Regular_triangulation Conflict_pred_in_subspace c( *this, p, coaffine_orientation_predicate(), - power_test_in_flat_predicate()); + power_side_of_power_sphere_for_non_maximal_dim_predicate()); Conflict_traversal_pred_in_subspace tp(*this, c); return tds().gather_full_cells(s, tp, out); } else { Orientation_d ori = geom_traits().orientation_d_object(); - Power_test_d side = geom_traits().power_test_d_object(); + Power_side_of_power_sphere_d side = geom_traits().power_side_of_power_sphere_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); Conflict_traversal_pred_in_fullspace tp(*this, c); return tds().gather_full_cells(s, tp, out); @@ -1095,8 +1112,8 @@ Regular_triangulation ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); if (!is_infinite(opposite_vh)) { - Power_test_d side = - geom_traits().power_test_d_object(); + Power_side_of_power_sphere_d side = + geom_traits().power_side_of_power_sphere_d_object(); if (side(Point_const_iterator(ch->vertices_begin()), Point_const_iterator(ch->vertices_end()), opposite_vh->point()) == ON_POSITIVE_SIDE) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 893de15a790..4479fda4baf 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -40,12 +40,13 @@ public: typedef typename K::Weighted_point_d Point_d; // Required by RegularTriangulationTraits - typedef typename K::Point_d Bare_point; - typedef typename K::Weighted_point_d Weighted_point; + typedef typename K::Point_d Bare_point_d; + typedef typename K::Weighted_point_d Weighted_point_d; typedef typename K::Point_drop_weight_d Point_drop_weight_d; typedef typename K::Point_weight_d Point_weight_d; - typedef typename K::Power_test_d Power_test_d; - typedef typename K::In_flat_power_test_d In_flat_power_test_d; + typedef typename K::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; + typedef typename K::In_flat_power_side_of_power_sphere_d + In_flat_power_side_of_power_sphere_d; //=========================================================================== // Custom types @@ -63,7 +64,7 @@ public: : m_kernel(kernel) {} result_type operator()( - Weighted_point const& p, Weighted_point const& q, int i) const + Weighted_point_d const& p, Weighted_point_d const& q, int i) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.less_coordinate_d_object() (pdw(p), pdw(q), i); @@ -160,7 +161,7 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end, - const Weighted_point & p) const + const Weighted_point_d & p) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.contained_in_affine_hull_d_object() ( @@ -185,7 +186,7 @@ public: : m_kernel(kernel) {} result_type operator()( - const Weighted_point & p, const Weighted_point & q) const + const Weighted_point_d & p, const Weighted_point_d & q) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.compare_lexicographically_d_object()(pdw(p), pdw(q)); @@ -206,7 +207,7 @@ public: : m_kernel(kernel) {} result_type operator()( - const Weighted_point & p, const int i) const + const Weighted_point_d & p, const int i) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.compute_coordinate_d_object()(pdw(p), i); @@ -228,7 +229,7 @@ public: : m_kernel(kernel) {} result_type operator()( - const Weighted_point & p) const + const Weighted_point_d & p) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.point_dimension_d_object()(pdw(p)); diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index 489f6b65805..2d8f98ca6a2 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -105,26 +105,188 @@ void test(const int d, const string & type, const int N) template< int D > void go(const int N) { - //typedef CGAL::Epick_d FK; typedef CGAL::Epick_d > FK; typedef CGAL::Regular_triangulation< CGAL::Regular_triangulation_euclidean_traits > Triangulation; - //test(D, "dynamic", N); test(D, "static", N); + + typedef CGAL::Epick_d FK_dyn; + typedef CGAL::Regular_triangulation< + CGAL::Regular_triangulation_euclidean_traits > Triangulation_dyn; + test(D, "dynamic", N); } +void test_inserting_points_at_the_same_position() +{ + const int DIM = 5; + typedef CGAL::Epick_d > FK; + typedef CGAL::Regular_triangulation< + CGAL::Regular_triangulation_euclidean_traits > RTri; + + typedef RTri::Vertex_handle Vertex_handle; + typedef RTri::Full_cell_handle Full_cell_handle; + typedef RTri::Face Face; + typedef RTri::Point Point; + typedef RTri::Bare_point Bare_point; + typedef RTri::Finite_full_cell_const_iterator Finite_full_cell_const_iterator; + typedef RTri::Finite_vertex_iterator Finite_vertex_iterator; + + RTri rt(DIM); + + cerr << "\nTesting insertion of points at the same position"; + assert(rt.empty()); + + std::vector pt; + pt.push_back(1.2); + pt.push_back(20.3); + pt.push_back(10.); + pt.push_back(8.); + pt.push_back(7.1); + + //======================= + + // First point + Vertex_handle vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.)); + assert(rt.number_of_vertices() == 1); + assert(rt.number_of_hidden_points() == 0); + assert(vh != Vertex_handle()); + + // Same point + Vertex_handle vh2 = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.)); + assert(rt.number_of_vertices() == 1); + assert(rt.number_of_hidden_points() == 0); + assert(vh == vh2); + + // Same position, bigger weight + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); + assert(rt.number_of_vertices() == 1); + assert(rt.number_of_hidden_points() == 1); + assert(vh != Vertex_handle()); + + // Same point + vh2 = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); + assert(rt.number_of_vertices() == 1); + assert(rt.number_of_hidden_points() == 1); + assert(vh == vh2); + + // Same position, lower weight + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.1)); + assert(rt.number_of_vertices() == 1); + assert(rt.number_of_hidden_points() == 2); + assert(vh == Vertex_handle()); + + //======================= + + // New position + pt[3] = 0.78; + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.)); + assert(rt.number_of_vertices() == 2); + assert(rt.number_of_hidden_points() == 2); + assert(vh != Vertex_handle()); + + // Same point + vh2 = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.)); + assert(rt.number_of_vertices() == 2); + assert(rt.number_of_hidden_points() == 2); + assert(vh == vh2); + + // Same position, bigger weight + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); + assert(rt.number_of_vertices() == 2); + assert(rt.number_of_hidden_points() == 3); + assert(vh != Vertex_handle()); + + // Same point + vh2 = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); + assert(rt.number_of_vertices() == 2); + assert(rt.number_of_hidden_points() == 3); + assert(vh == vh2); + + // Same position, lower weight + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.1)); + assert(rt.number_of_vertices() == 2); + assert(rt.number_of_hidden_points() == 4); + assert(vh == Vertex_handle()); + + //======================= + + // New position + pt[4] = 1.78; + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.2)); + assert(rt.number_of_vertices() == 3); + assert(rt.number_of_hidden_points() == 4); + assert(vh != Vertex_handle()); + + //======================= + + // New position + pt[1] = 1.78; + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.8)); + assert(rt.number_of_vertices() == 4); + assert(rt.number_of_hidden_points() == 4); + assert(vh != Vertex_handle()); + + //======================= + + // New position + pt[2] = 1.78; + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.25)); + assert(rt.number_of_vertices() == 5); + assert(rt.number_of_hidden_points() == 4); + assert(vh != Vertex_handle()); + + //======================= + + // New position + pt[0] = 12.13; + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.25)); + assert(rt.number_of_vertices() == 6); + assert(rt.number_of_hidden_points() == 4); + assert(vh != Vertex_handle()); + + // Same position, bigger weight + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); + assert(rt.number_of_vertices() == 6); + assert(rt.number_of_hidden_points() == 5); + assert(vh != Vertex_handle()); + + //======================= + + // New position + pt[0] = 9.13; + vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.25)); + assert(rt.number_of_vertices() == 7); + assert(rt.number_of_hidden_points() == 5); + assert(vh != Vertex_handle()); + + //======================= + + cerr << "\nChecking topology and geometry..."; + assert(rt.is_valid(true)); + + rt.clear(); + assert(-1 == rt.current_dimension()); + assert(rt.empty()); + assert(rt.is_valid()); + //std::cerr << ((rt.is_valid(true)) ? "VALID!" : "NOT VALID :(") << std::endl; +} + + int main(int argc, char **argv) { srand(static_cast(time(NULL))); int N = 10; if( argc > 1 ) N = atoi(argv[1]); + + test_inserting_points_at_the_same_position(); + //go<5>(N); go<4>(N); go<3>(N); go<2>(N); go<1>(N); - + cerr << endl; return 0; } From ac0c86dc404731d2c30ed4c1dcd9792ffad8c37f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 24 May 2016 14:53:35 +0200 Subject: [PATCH 431/487] Explain "in conflict" --- Triangulation/doc/Triangulation/Triangulation.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index b006eaf0647..d91e3dba71f 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -480,6 +480,9 @@ of all simplices are regular. Note that as a result, some points can be hidden and do not result in vertices in the triangulation. +A weighted point `p` is said to be in conflict +with a cell `c` if it has a negative power distance to the power sphere of `c`. + Regular triangulations support insertion of weighted points, and location of a query point inside the triangulation. Note that inserting a large set of points at once is much faster From 39c98f2fea555b94bf9e6b2ec235542402d1d9b4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 24 May 2016 14:53:49 +0200 Subject: [PATCH 432/487] Clean-up --- Triangulation/test/Triangulation/test_torture.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Triangulation/test/Triangulation/test_torture.cpp b/Triangulation/test/Triangulation/test_torture.cpp index 3ec215278b9..d75b560791a 100644 --- a/Triangulation/test/Triangulation/test_torture.cpp +++ b/Triangulation/test/Triangulation/test_torture.cpp @@ -82,11 +82,7 @@ void test(const int D, const int d, const int N, bool no_transform) for( int j = 0; j < d; ++j ) coords[i] = coords[i] + (*pit)[j] * aff[j][i]; } -#ifdef USE_NEW_KERNEL - points.push_back(Point(coords)); // this is for New_kernel_d -#else - points.push_back(Point(D, coords.begin(), coords.end())); // this is for Old_kernel_d -#endif + points.push_back(Point(D, coords.begin(), coords.end())); } assert( dc.is_valid() ); cout << " Inserting " << points.size() << " points."; From 5eac4b8bdcd2214ea19446c23c61a3064d6e3f07 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 24 May 2016 14:56:59 +0200 Subject: [PATCH 433/487] Test both static and dynamic kernels --- Triangulation/test/Triangulation/test_delaunay.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Triangulation/test/Triangulation/test_delaunay.cpp b/Triangulation/test/Triangulation/test_delaunay.cpp index 751b42133b3..bd2bb695ed3 100644 --- a/Triangulation/test/Triangulation/test_delaunay.cpp +++ b/Triangulation/test/Triangulation/test_delaunay.cpp @@ -113,11 +113,13 @@ void test(const int d, const string & type, const int N) template< int D > void go(const int N) { - //typedef CGAL::Epick_d FK; typedef CGAL::Epick_d > FK; typedef CGAL::Delaunay_triangulation Triangulation; - //test(D, "dynamic", N); test(D, "static", N); + + typedef CGAL::Epick_d FK_dyn; + typedef CGAL::Delaunay_triangulation Triangulation_dyn; + test(D, "dynamic", N); } int main(int argc, char **argv) From 5f33eaad17a88ab31a219049368393e4a30e8084 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 24 May 2016 15:22:40 +0200 Subject: [PATCH 434/487] CGAL always computes a unique triangulation, even in degenerate cases --- Triangulation/doc/Triangulation/Triangulation.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index d91e3dba71f..84599d8793a 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -396,11 +396,8 @@ circumscribing ball whose interior does not contain any vertex of the triangulation. In case of degeneracies (co-spherical points) the triangulation is not -uniquely defined. Note however that the \cgal implementation computes -one of the possible Delaunay triangulations. -The computed triangulation is uniquely defined for a given insertion -order of the points (which is always the same if inserted using -`CGAL::Delaunay_triangulation::insert(ForwardIterator s, ForwardIterator e)`). +uniquely defined. Note however that the CGAL implementation computes a +unique triangulation even in these cases. When a new point `p` is inserted into a Delaunay triangulation, the full cells whose circumscribing ball contains `p` are said to From 5b0f8e15be7e0a5da215dd33a4308f2b0bbd0fbe Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 25 May 2016 18:26:37 +0200 Subject: [PATCH 435/487] Document number_of_hidden_vertices + clarify user manual --- .../CGAL/Regular_triangulation.h | 16 ++++++++++ .../doc/Triangulation/Triangulation.txt | 2 +- .../include/CGAL/Regular_triangulation.h | 2 +- .../test/Triangulation/test_regular.cpp | 32 +++++++++---------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 5cf79f1cf22..db2e856997d 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -184,5 +184,21 @@ OutputIterator out) const; /// @} +/// \name Access Functions +/// @{ + +/*! +Returns the number of finite vertices that are not hidden. +*/ +size_type number_of_vertices() const; + +/*! +Returns the number of hidden vertices. +*/ +size_type number_of_hidden_vertices() const; + +/// @} + + }; /* end regular_triangulation */ } /* end namespace CGAL */ diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 84599d8793a..8b3953860b0 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -475,7 +475,7 @@ A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres of all simplices are regular. Note that as a result, some points can be hidden and do not result in vertices -in the triangulation. +in the triangulation. Those points are discarded and cannot be retrieved. A weighted point `p` is said to be in conflict with a cell `c` if it has a negative power distance to the power sphere of `c`. diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 48bd49058ab..0303b210dad 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -384,7 +384,7 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MISC - std::size_t number_of_hidden_points() const + std::size_t number_of_hidden_vertices() const { return m_hidden_points.size(); } diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index 2d8f98ca6a2..0086773abc6 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -148,31 +148,31 @@ void test_inserting_points_at_the_same_position() // First point Vertex_handle vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.)); assert(rt.number_of_vertices() == 1); - assert(rt.number_of_hidden_points() == 0); + assert(rt.number_of_hidden_vertices() == 0); assert(vh != Vertex_handle()); // Same point Vertex_handle vh2 = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.)); assert(rt.number_of_vertices() == 1); - assert(rt.number_of_hidden_points() == 0); + assert(rt.number_of_hidden_vertices() == 0); assert(vh == vh2); // Same position, bigger weight vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); assert(rt.number_of_vertices() == 1); - assert(rt.number_of_hidden_points() == 1); + assert(rt.number_of_hidden_vertices() == 1); assert(vh != Vertex_handle()); // Same point vh2 = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); assert(rt.number_of_vertices() == 1); - assert(rt.number_of_hidden_points() == 1); + assert(rt.number_of_hidden_vertices() == 1); assert(vh == vh2); // Same position, lower weight vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.1)); assert(rt.number_of_vertices() == 1); - assert(rt.number_of_hidden_points() == 2); + assert(rt.number_of_hidden_vertices() == 2); assert(vh == Vertex_handle()); //======================= @@ -181,31 +181,31 @@ void test_inserting_points_at_the_same_position() pt[3] = 0.78; vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.)); assert(rt.number_of_vertices() == 2); - assert(rt.number_of_hidden_points() == 2); + assert(rt.number_of_hidden_vertices() == 2); assert(vh != Vertex_handle()); // Same point vh2 = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.)); assert(rt.number_of_vertices() == 2); - assert(rt.number_of_hidden_points() == 2); + assert(rt.number_of_hidden_vertices() == 2); assert(vh == vh2); // Same position, bigger weight vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); assert(rt.number_of_vertices() == 2); - assert(rt.number_of_hidden_points() == 3); + assert(rt.number_of_hidden_vertices() == 3); assert(vh != Vertex_handle()); // Same point vh2 = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); assert(rt.number_of_vertices() == 2); - assert(rt.number_of_hidden_points() == 3); + assert(rt.number_of_hidden_vertices() == 3); assert(vh == vh2); // Same position, lower weight vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.1)); assert(rt.number_of_vertices() == 2); - assert(rt.number_of_hidden_points() == 4); + assert(rt.number_of_hidden_vertices() == 4); assert(vh == Vertex_handle()); //======================= @@ -214,7 +214,7 @@ void test_inserting_points_at_the_same_position() pt[4] = 1.78; vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.2)); assert(rt.number_of_vertices() == 3); - assert(rt.number_of_hidden_points() == 4); + assert(rt.number_of_hidden_vertices() == 4); assert(vh != Vertex_handle()); //======================= @@ -223,7 +223,7 @@ void test_inserting_points_at_the_same_position() pt[1] = 1.78; vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.8)); assert(rt.number_of_vertices() == 4); - assert(rt.number_of_hidden_points() == 4); + assert(rt.number_of_hidden_vertices() == 4); assert(vh != Vertex_handle()); //======================= @@ -232,7 +232,7 @@ void test_inserting_points_at_the_same_position() pt[2] = 1.78; vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 0.25)); assert(rt.number_of_vertices() == 5); - assert(rt.number_of_hidden_points() == 4); + assert(rt.number_of_hidden_vertices() == 4); assert(vh != Vertex_handle()); //======================= @@ -241,13 +241,13 @@ void test_inserting_points_at_the_same_position() pt[0] = 12.13; vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.25)); assert(rt.number_of_vertices() == 6); - assert(rt.number_of_hidden_points() == 4); + assert(rt.number_of_hidden_vertices() == 4); assert(vh != Vertex_handle()); // Same position, bigger weight vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.3)); assert(rt.number_of_vertices() == 6); - assert(rt.number_of_hidden_points() == 5); + assert(rt.number_of_hidden_vertices() == 5); assert(vh != Vertex_handle()); //======================= @@ -256,7 +256,7 @@ void test_inserting_points_at_the_same_position() pt[0] = 9.13; vh = rt.insert(Point(Bare_point(pt.begin(), pt.end()), 1.25)); assert(rt.number_of_vertices() == 7); - assert(rt.number_of_hidden_points() == 5); + assert(rt.number_of_hidden_vertices() == 5); assert(vh != Vertex_handle()); //======================= From 890b4ef0aaf1bd2891db9179ecbf7b26e3ba0477 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 27 May 2016 10:58:48 +0200 Subject: [PATCH 436/487] Doc fixes + make the use of Regular_triangulation_euclidean_traits automatic Partially reverts commit ab30798119caea88e975919b53987ab443c15067 --- .../doc/Triangulation/CGAL/Triangulation.h | 2 +- .../Concepts/RegularTriangulationTraits.h | 18 ++++++++++-------- .../Concepts/TriangulationTraits.h | 2 +- .../Triangulation/regular_triangulation.cpp | 3 +-- .../include/CGAL/Regular_triangulation.h | 10 +++++----- .../test/Triangulation/test_regular.cpp | 9 +++------ 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index ce482d4b255..a6fedb22067 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -212,7 +212,7 @@ type (a signed integral type) typedef TriangulationDataStructure_::difference_type difference_type; /*! -used by `Triangulation` to specify which case occurs when locating a point in the triangulation +\enum used by `Triangulation` to specify which case occurs when locating a point in the triangulation */ enum Locate_type { ON_VERTEX=0, /*!< when the located point coincides with a vertex of the triangulation */ IN_FACE, /*!< when the point is in the interior of a face of dimension equal or less than `maximal_dimension()` - 2 */ diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 1225347bf6b..d313caa5f03 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -7,9 +7,11 @@ This concept describes the geometric types and predicates required to build a regular triangulation. It corresponds to the first template parameter of the class `CGAL::Regular_triangulation`. -\cgalRefines TriangulationTraits. +\cgalRefines `TriangulationTraits` -\cgalHasModel `CGAL::Regular_triangulation_euclidean_traits` +\cgalHasModel `CGAL::Epick_d` + +\sa `TriangulationTraits` */ class RegularTriangulationTraits { public: @@ -51,15 +53,15 @@ A predicate object that must provide the templated operator `template Oriented_side operator()(ForwardIterator start, ForwardIterator end, const Weighted_point_d & p)`. Let \f$ S \f$ be the power sphere of the weighted points in range `[start,end)`. The operator returns: -- `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to - \f$ S \f$, +- `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to +\f$ S \f$, -- `ON_NEGATIVE_SIDE` if the power distance between `p` and \f$ S \f$ is +- `ON_NEGATIVE_SIDE` if the power distance between `p` and \f$ S \f$ is positive. - `ON_POSITIVE_SIDE` otherwise. -\pre If `Dimension` is `CGAL::Dimension_tag`, +\pre If `Dimension` is `CGAL::Dimension_tag`, then `std::distance(start,end)=D+1`. The weighted points in range `[start,end)` must be affinely independent, i.e., the simplex must @@ -80,14 +82,14 @@ The operator returns: - `ON_ORIENTED_BOUNDARY` if `p` is orthogonal to \f$ S \f$, -- `ON_NEGATIVE_SIDE` if the power distance between `p` and \f$ S \f$ is +- `ON_NEGATIVE_SIDE` if the power distance between `p` and \f$ S \f$ is positive. - `ON_POSITIVE_SIDE` otherwise. \pre `std::distance(start,end)=k+1` where \f$ k\f$ is the number of points used to construct `orient` (dimension of the flat). -The points in range `[start,end)` must be affinely independent. +The points in range `[start,end)` must be affinely independent. `p` must be in the flat generated by these points. */ typedef unspecified_type In_flat_power_side_of_power_sphere_d; diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h index 8d997b84e40..9791e86d42f 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationTraits.h @@ -131,7 +131,7 @@ the same and `LARGER` otherwise. */ typedef unspecified_type Compare_lexicographically_d; -/// @} +/// @} /// \name Creation /// @{ diff --git a/Triangulation/examples/Triangulation/regular_triangulation.cpp b/Triangulation/examples/Triangulation/regular_triangulation.cpp index bae40c7711a..a8a917db17e 100644 --- a/Triangulation/examples/Triangulation/regular_triangulation.cpp +++ b/Triangulation/examples/Triangulation/regular_triangulation.cpp @@ -10,8 +10,7 @@ const int D = 5; // Dimension const int N = 100; // Number of points typedef CGAL::Epick_d< CGAL::Dimension_tag > K; -typedef CGAL::Regular_triangulation< - CGAL::Regular_triangulation_euclidean_traits > T; +typedef CGAL::Regular_triangulation T; typedef T::Bare_point Bare_point; typedef T::Weighted_point Weighted_point; diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 0303b210dad..c9da2cdfb25 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -33,17 +33,17 @@ namespace CGAL { template< typename Traits_, typename TDS_ = Default > class Regular_triangulation : public Triangulation< - Traits_, + Regular_triangulation_euclidean_traits, typename Default::Get< TDS_, Triangulation_data_structure< - typename Traits_::Dimension, - Triangulation_vertex, - Triangulation_full_cell + typename Regular_triangulation_euclidean_traits::Dimension, + Triangulation_vertex >, + Triangulation_full_cell > > >::type> { - typedef Traits_ RTTraits; + typedef Regular_triangulation_euclidean_traits RTTraits; typedef typename RTTraits::Dimension Maximal_dimension_; typedef typename Default::Get< TDS_, diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index 0086773abc6..2ffd84892b6 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -106,13 +106,11 @@ template< int D > void go(const int N) { typedef CGAL::Epick_d > FK; - typedef CGAL::Regular_triangulation< - CGAL::Regular_triangulation_euclidean_traits > Triangulation; + typedef CGAL::Regular_triangulation Triangulation; test(D, "static", N); typedef CGAL::Epick_d FK_dyn; - typedef CGAL::Regular_triangulation< - CGAL::Regular_triangulation_euclidean_traits > Triangulation_dyn; + typedef CGAL::Regular_triangulation Triangulation_dyn; test(D, "dynamic", N); } @@ -120,8 +118,7 @@ void test_inserting_points_at_the_same_position() { const int DIM = 5; typedef CGAL::Epick_d > FK; - typedef CGAL::Regular_triangulation< - CGAL::Regular_triangulation_euclidean_traits > RTri; + typedef CGAL::Regular_triangulation RTri; typedef RTri::Vertex_handle Vertex_handle; typedef RTri::Full_cell_handle Full_cell_handle; From 993bef7774108d2c6f10ad9b8fb053a29500b41c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 27 May 2016 11:10:29 +0200 Subject: [PATCH 437/487] Add a comment to explain how Regular_triangulation_euclidean_traits works + remove misleading template parameter list in the doc --- .../doc/Triangulation/CGAL/Regular_triangulation.h | 2 +- .../include/CGAL/Regular_triangulation_euclidean_traits.h | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index db2e856997d..9e434d0b329 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -42,7 +42,7 @@ tag `CGAL::Default` as the second parameter. */ template< typename RegularTriangulationTraits_, typename TriangulationDataStructure_ > class Regular_triangulation - : public Triangulation + : public Triangulation { public: diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 4479fda4baf..0275a842d48 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -26,6 +26,14 @@ namespace CGAL { +// Wrapper class to make a model of `RegularTriangulationTraits` easily usable +// by the `Regular_triangulation` class. By using this class: +// - Point_d (used by `Triangulation` and the TDS) becomes a weighted point +// - Predicates and functors such as Less_coordinate_d or Orientation_d +// can be called using weighted points instead of bare points (this is +// needed because `Weighted_point_d` is not convertible to `Point_d`) +// This way, `Triangulation` works perfectly well with weighted points. + template class Regular_triangulation_euclidean_traits : public K From ccaeeb4a898c8d107cfc73ff3e46207c2f90cad2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 31 May 2016 16:20:32 +0200 Subject: [PATCH 438/487] Add a note on Point_d if in the Regular_triangulation context --- Triangulation/doc/Triangulation/CGAL/Triangulation.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index a6fedb22067..1175a96cb26 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -63,7 +63,9 @@ Type for the model of the `TriangulationTraits_` concept. typedef TriangulationTraits_ Geom_traits; /*! -A point in Euclidean space. +A point in Euclidean space. Note that in the context of a +`Regular_triangulation` class (which derives from this class), +`TriangulationTraits_::Point_d` is a weighted point. */ typedef TriangulationTraits_::Point_d Point; From 1b4e3e70a5acc4b70275b3738962a0e0bc2185c7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 31 May 2016 17:23:47 +0200 Subject: [PATCH 439/487] Document Regular_triangulation_euclidean_traits properly --- .../CGAL/Regular_triangulation.h | 3 +- .../Regular_triangulation_euclidean_traits.h | 61 +++++++++++++++++++ .../doc/Triangulation/PackageDescription.txt | 7 +++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 9e434d0b329..3f0b881c44f 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -38,11 +38,12 @@ tag `CGAL::Default` as the second parameter. \sa `Delaunay_triangulation` \sa `Triangulation_data_structure` +\sa `Regular_triangulation_euclidean_traits` */ template< typename RegularTriangulationTraits_, typename TriangulationDataStructure_ > class Regular_triangulation - : public Triangulation + : public Triangulation, TriangulationDataStructure_> { public: diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h new file mode 100644 index 00000000000..2f20cfa581b --- /dev/null +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h @@ -0,0 +1,61 @@ + +namespace CGAL { + +/*! +\ingroup PkgTriangulationsTraitsClasses + +The class `Regular_triangulation_euclidean_traits` is used iternally by the +class `Regular_triangulation` to wrap its first template parameter +(`RegularTriangulationTraits_`) +so that the base class `Triangulation` manipulates weighted points instead +of bare points. + +\tparam K must be a model of the `RegularTriangulationTraits` concept. + +In addition to the types described below, the following predicates and functors +are adapted so that they can be called +with weighted points as parameters. In practice, the functors from the +base class `K` are called, ignoring the weights. +- `Orientation_d` +- `Construct_flat_orientation_d` +- `In_flat_orientation_d` +- `Contained_in_affine_hull_d` +- `Compare_lexicographically_d` +- `Compute_coordinate_d` +- `Point_dimension_d` +- `Less_coordinate_d` + +*/ + +template +class Regular_triangulation_euclidean_traits : public K { +public: + + /// \name Types + /// @{ + + /*! + The weighted point type. + */ + typedef typename K::Weighted_point_d Point_d; + + /*! + The (un-weighted) point type. + */ + typedef typename K::Point_d Bare_point_d; + + /// @} + + /// \name Creation + /// @{ + + /*! + The default constructor. + */ + Regular_triangulation_euclidean_traits(); + + /// @} + +}; + +} /* end namespace CGAL */ diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 845a1a519b0..4937cbba3e1 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -5,6 +5,9 @@ /// \defgroup PkgTriangulationsTriangulationClasses Triangulation Classes /// \ingroup PkgTriangulations +/// \defgroup PkgTriangulationsTraitsClasses Traits Classes +/// \ingroup PkgTriangulations + /// \defgroup PkgTriangulationsVertexCellClasses Vertex, Face and Cell Classes /// \ingroup PkgTriangulations @@ -107,6 +110,10 @@ The latter two concepts are also abbreviated respectively as `TrVertex` and `TrF - `CGAL::Triangulation_vertex` - `CGAL::Triangulation_full_cell` +## Traits Classes ## + +- `CGAL::Regular_triangulation_euclidean_traits` + ## Enums ## - `CGAL::Triangulation::Locate_type` From 742f2340c3d882076903c1372cc79a31dd59ef38 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 31 May 2016 17:28:51 +0200 Subject: [PATCH 440/487] Missing type "Point" --- Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h b/Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h index c0f13c4e2e2..ddb31b55090 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation_vertex.h @@ -43,6 +43,11 @@ public: /// \name Types /// @{ +/*! +The point type. +*/ +typedef TriangulationTraits_::Point_d Point; + /*! The type of the additional data stored in the vertex. If you read a `Triangulation_vertex` from a stream (a file) or write a `Triangulation_vertex` to a stream, then streaming operators `<<` and `>>` must be provided for this From 350b0c017601185b7e93076368a70a43bd83e64d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 31 May 2016 17:45:13 +0200 Subject: [PATCH 441/487] Typo --- .../Triangulation/CGAL/Regular_triangulation_euclidean_traits.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h index 2f20cfa581b..02bf34e03ca 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h @@ -4,7 +4,7 @@ namespace CGAL { /*! \ingroup PkgTriangulationsTraitsClasses -The class `Regular_triangulation_euclidean_traits` is used iternally by the +The class `Regular_triangulation_euclidean_traits` is used internally by the class `Regular_triangulation` to wrap its first template parameter (`RegularTriangulationTraits_`) so that the base class `Triangulation` manipulates weighted points instead From b5e8e58d4866a15bdd4a6e32eb14c8f450e3bf2b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 1 Jun 2016 11:54:56 +0200 Subject: [PATCH 442/487] More explicit sentence --- .../CGAL/Regular_triangulation_euclidean_traits.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h index 02bf34e03ca..049b1d379df 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h @@ -14,8 +14,9 @@ of bare points. In addition to the types described below, the following predicates and functors are adapted so that they can be called -with weighted points as parameters. In practice, the functors from the -base class `K` are called, ignoring the weights. +with weighted points instead of bare points as parameters. +In practice, the functors from the base class `K` are called, +ignoring the weights. - `Orientation_d` - `Construct_flat_orientation_d` - `In_flat_orientation_d` From c752dea8e08251e61178edc6596837cd2abc3883 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 24 Feb 2015 14:00:28 +0100 Subject: [PATCH 443/487] Link Power_center_d. (cherry picked from commit f4de16d0932a9ace0297e6433a1343528cc8dac6) Conflicts: NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h NewKernel_d/test/NewKernel_d/Epick_d.cpp --- .../include/CGAL/NewKernel_d/Kernel_d_interface.h | 2 ++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index 22e0272d5ad..e1df0f6d62a 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -66,6 +66,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Point_dimension_d; typedef typename Get_functor::type Side_of_oriented_sphere_d; typedef typename Get_functor::type Power_side_of_power_sphere_d; + typedef typename Get_functor::type Power_center_d; typedef typename Get_functor::type Contained_in_affine_hull_d; typedef typename Get_functor::type Construct_flat_orientation_d; typedef typename Get_functor::type In_flat_orientation_d; @@ -188,6 +189,7 @@ template struct Kernel_d_interface : public Base_ { Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); } Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); } + Power_center_d power_center_d_object()const{ return Power_center_d(*this); } Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); } Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); } diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 264ba6fe4a6..db1681171c6 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -135,6 +135,13 @@ void test2(){ typedef typename K1::Construct_min_vertex_d CmV; typedef typename K1::Construct_max_vertex_d CMV; typedef typename K1::Compute_squared_radius_d SR; + typedef typename K1::Translated_point_d TP; + typedef typename K1::Power_center_d PC; + typedef typename CGAL::Get_functor::type PoD; + typedef typename K1::Weighted_point_d WP; + typedef typename K1::Construct_weighted_point_d CWP; + typedef typename K1::Point_drop_weight_d PDW; + typedef typename K1::Point_weight_d PW; CGAL_USE_TYPE(AT); CGAL_USE_TYPE(D); @@ -196,6 +203,12 @@ void test2(){ CmV cmv Kinit(construct_min_vertex_d_object); CMV cMv Kinit(construct_max_vertex_d_object); SR sr Kinit(compute_squared_radius_d_object); + TP tp Kinit(translated_point_d_object); + PC pc Kinit(power_center_d_object); + CWP cwp Kinit(construct_weighted_point_d_object); + PDW pdw Kinit(point_drop_weight_d_object); + PW pw Kinit(point_weight_d_object); + PoD pod (k); CGAL_USE(bc); CGAL_USE(pol); From ba50bc5b9ce2972fc6b1da3973be98c91a579497 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 21 Oct 2014 17:20:20 +0200 Subject: [PATCH 444/487] Power_center. (cherry picked from commit 8c5e28cd3d44f2786cef1dc26604fbff32e5a1db) Conflicts: NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h NewKernel_d/test/NewKernel_d/Epick_d.cpp --- .../include/CGAL/NewKernel_d/Types/Sphere.h | 1 - .../CGAL/NewKernel_d/Types/Weighted_point.h | 80 +++++++++++++++++++ .../include/CGAL/NewKernel_d/functor_tags.h | 3 + NewKernel_d/test/NewKernel_d/Epick_d.cpp | 11 +++ 4 files changed, 94 insertions(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h index ec565f2cc8c..114410b4e76 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h @@ -52,7 +52,6 @@ template struct Construct_sphere : Store_kernel { } template result_type operator()(Iter f, Iter e)const{ - typedef typename Get_type::type Point; typename Get_functor::type cc(this->kernel()); typename Get_functor::type sd(this->kernel()); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 4896d40e882..1caf8701496 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -75,6 +75,33 @@ template struct Point_weight { } }; +template struct Power_distance : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_distance) + typedef typename Get_type::type first_argument_type; + typedef first_argument_type second_argument_type; + typedef typename Get_type::type result_type; + + result_type operator()(first_argument_type const&a, second_argument_type const&b)const{ + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor::type sd(this->kernel()); + return sd(pdw(a),pdw(b))-pw(a)-pw(b); + } +}; +template struct Power_distance_to_point : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_distance_to_point) + typedef typename Get_type::type first_argument_type; + typedef typename Get_type::type second_argument_type; + typedef typename Get_type::type result_type; + + result_type operator()(first_argument_type const&a, second_argument_type const&b)const{ + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor::type sd(this->kernel()); + return sd(pdw(a),b)-pw(a); + } +}; + template struct Power_side_of_power_sphere : private Store_kernel { CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere) typedef R_ R; @@ -114,6 +141,56 @@ template struct In_flat_power_side_of_power_sphere : private Store_ker } }; +// Construct a point at (weighted) distance 0 from all the input +template struct Power_center : Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_center) + typedef typename Get_type::type WPoint; + typedef WPoint result_type; + typedef typename Get_type::type Point; + typedef typename Get_type::type FT; + template + result_type operator()(Iter f, Iter e)const{ + // 2*(x-y).c == (x^2-wx^2)-(y^2-wy^2) + typedef typename R_::LA LA; + typedef typename LA::Square_matrix Matrix; + typedef typename LA::Vector Vec; + typedef typename LA::Construct_vector CVec; + typename Get_functor::type c(this->kernel()); + typename Get_functor >::type cp(this->kernel()); + typename Get_functor::type pd(this->kernel()); + typename Get_functor::type sdo(this->kernel()); + typename Get_functor::type pdp(this->kernel()); + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor >::type cwp(this->kernel()); + + WPoint const& wp0 = *f; + Point const& p0 = pdw(wp0); + int d = pd(p0); + FT const& n0 = sdo(p0) - pw(wp0); + Matrix m(d,d); + Vec b = typename CVec::Dimension()(d); + // Write the point coordinates in lines. + int i; + for(i=0; ++f!=e; ++i) { + WPoint const& wp=*f; + Point const& p=pdw(wp); + FT const& np = sdo(p) - pw(wp); + for(int j=0;j),(Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(Weighted_point_tag,Point_tag),()); @@ -121,5 +198,8 @@ CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_d CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere),(Weighted_point_tag),(Power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag)); CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere),(Weighted_point_tag),(In_flat_power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_distance_tag,(CartesianDKernelFunctors::Power_distance),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_distance_to_point_tag,(CartesianDKernelFunctors::Power_distance_to_point),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_center_tag,(CartesianDKernelFunctors::Power_center),(Weighted_point_tag,Point_tag),(Compute_point_cartesian_coordinate_tag,Construct_ttag,Construct_ttag,Point_dimension_tag,Squared_distance_to_origin_tag,Point_drop_weight_tag,Point_weight_tag,Power_distance_to_point_tag)); } // namespace CGAL #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index f0459906574..b8e17886e17 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -216,6 +216,8 @@ namespace CGAL { CGAL_DECL_COMPUTE(Hyperplane_translation); CGAL_DECL_COMPUTE(Value_at); CGAL_DECL_COMPUTE(Point_weight); + CGAL_DECL_COMPUTE(Power_distance); + CGAL_DECL_COMPUTE(Power_distance_to_point); #undef CGAL_DECL_COMPUTE #define CGAL_DECL_ITER_OBJ(X,Y,Z,C) struct X##_tag {}; \ @@ -269,6 +271,7 @@ namespace CGAL { CGAL_DECL_CONSTRUCT(Construct_max_vertex,Point); CGAL_DECL_CONSTRUCT(Construct_circumcenter,Point); CGAL_DECL_CONSTRUCT(Point_drop_weight,Point); + CGAL_DECL_CONSTRUCT(Power_center,Weighted_point); #undef CGAL_DECL_CONSTRUCT #if 0 #define CGAL_DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \ diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index db1681171c6..28be68c65ab 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -84,6 +84,7 @@ void test2(){ typedef typename K1::Ray_d R; typedef typename K1::Iso_box_d IB; typedef typename K1::Flat_orientation_d FO; + typedef typename K1::Weighted_point_d WP; //typedef K1::Construct_point CP; typedef typename K1::Construct_point_d CP; @@ -378,6 +379,16 @@ void test2(){ assert(cc(tr,0)==4); assert(cc(tr,1)==5); + WP tw[]={cwp(cp(5,0),1.5),cwp(cp(2,std::sqrt(3)),1),cwp(cp(2,-std::sqrt(3)),1)}; + WP xw=pc(tw+0,tw+3); + assert(abs(pod(xw,tw[0]))<.0001); + assert(abs(pod(xw,tw[1]))<.0001); + assert(abs(pod(xw,tw[2]))<.0001); + assert(pdw(xw)[0]<2.95); + assert(pdw(xw)[0]>2.5); + assert(pw(xw)<2.95); + assert(pw(xw)>2.5); + Sp un1; CGAL_USE(un1); H un2; CGAL_USE(un2); S un3; CGAL_USE(un3); From 95ab3b14027e1bb7fb7e90104098a95ec7efc9ad Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 11:08:47 +0200 Subject: [PATCH 445/487] Remove the using and call the base's operator() explicitly --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 125bc0b4057..43632010d4d 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -91,16 +91,15 @@ public: struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{ PointPropertyMap ppmap; - using Base_traits::Construct_cartesian_const_iterator_d::operator(); Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_) :Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){} typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p) const - { return this->operator() (get(ppmap,p)); } + { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p)); } typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const - { return this->operator() (get(ppmap,p),0); } + { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p),0); } }; struct Construct_iso_box_d: public Base::Construct_iso_box_d{ From cd6cd2918beaaf7730747bd525ed4a73228f9dd5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 15:47:59 +0200 Subject: [PATCH 446/487] Add explicit forwarder to the Base_traits --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 43632010d4d..83b600c9575 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -91,7 +91,7 @@ public: struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{ PointPropertyMap ppmap; - + Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_) :Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){} @@ -100,6 +100,12 @@ public: typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p),0); } + + typename Base_traits::Cartesian_const_iterator_d operator()(const typename Base_traits::Point_d& p) const + { return Base_traits::Construct_cartesian_const_iterator_d::operator() (p); } + + typename Base_traits::Cartesian_const_iterator_d operator()(const typename Base_traits::Point_d& p, int) const + { return Base_traits::Construct_cartesian_const_iterator_d::operator() (p,0); } }; struct Construct_iso_box_d: public Base::Construct_iso_box_d{ From b92138cde53fa988341fe554fdc487c5361895d5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 16:30:46 +0200 Subject: [PATCH 447/487] Add a comment about the two new operators --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 83b600c9575..47b711ddc30 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -101,6 +101,11 @@ public: typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p),0); } + // These 2 additional operators forward the call to Base_traits. + // This is needed because of an undocumented requirement of + // Orthogonal_k_neighbor_search and Orthogonal_incremental_neighbor_search: + // Traits::Construct_cartesian_const_iterator should be callable + // on the query point type typename Base_traits::Cartesian_const_iterator_d operator()(const typename Base_traits::Point_d& p) const { return Base_traits::Construct_cartesian_const_iterator_d::operator() (p); } From d984aca01082439eac78c801c2dccd4324e83217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 18 Nov 2014 11:33:31 +0100 Subject: [PATCH 448/487] Fix trailing whitespace --- .../include/CGAL/Delaunay_triangulation.h | 42 ++--- .../CGAL/IO/Triangulation_off_ostream.h | 18 +-- .../include/CGAL/Regular_triangulation.h | 146 +++++++++--------- 3 files changed, 103 insertions(+), 103 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index bb53bc5c489..49a8210b649 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -72,10 +72,10 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Vertex_const_handle Vertex_const_handle; typedef typename Base::Vertex_const_iterator Vertex_const_iterator; - typedef typename Base::Full_cell_handle Full_cell_handle; - typedef typename Base::Full_cell_iterator Full_cell_iterator; - typedef typename Base::Full_cell_const_handle Full_cell_const_handle; - typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename Base::Full_cell_handle Full_cell_handle; + typedef typename Base::Full_cell_iterator Full_cell_iterator; + typedef typename Base::Full_cell_const_handle Full_cell_const_handle; + typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; typedef typename Base::Finite_full_cell_const_iterator Finite_full_cell_const_iterator; @@ -124,7 +124,7 @@ public: using Base::vertices_begin; using Base::vertices_end; // using Base:: - + private: //*** Side_of_oriented_subsphere_d *** typedef typename Base::Flat_orientation_d Flat_orientation_d; @@ -161,12 +161,12 @@ public: } // With this constructor, - // the user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension // (= preset_flat_orientation_.first) // It it used by the dark triangulations created by DT::remove Delaunay_triangulation( - int dim, + int dim, const std::pair &preset_flat_orientation, const Geom_traits &k = Geom_traits()) : Base(dim, preset_flat_orientation, k) @@ -181,8 +181,8 @@ public: Side_of_oriented_subsphere_d side_of_oriented_subsphere_predicate() const { return Side_of_oriented_subsphere_d ( - flat_orientation_, - geom_traits().construct_flat_orientation_d_object(), + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), geom_traits().in_flat_side_of_oriented_sphere_d_object() ); } @@ -294,7 +294,7 @@ public: Orientation o = ori_( boost::make_transform_iterator(s->vertices_begin(), spivi), - boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, spivi)); if( POSITIVE == o ) @@ -323,9 +323,9 @@ public: return pred_(dc_.full_cell(f)->neighbor(dc_.index_of_covertex(f))); } }; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY - + bool is_valid(bool verbose = false, int level = 0) const; private: @@ -342,7 +342,7 @@ private: Conflict_traversal_pred_in_fullspace; }; -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // FUNCTIONS THAT ARE MEMBER METHODS: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS @@ -515,7 +515,7 @@ Delaunay_triangulation typedef typename Base::template Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); - + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); // Make the dark simplices in the conflict zone searchable conflict_zone.make_searchable(); @@ -613,7 +613,7 @@ Delaunay_triangulation int li = light_s->index(dark_s->vertex(di)->data()); Rotor light_r(light_s, li, light_i); typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); - + while (simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r)))) light_r = rotate_rotor(light_r); @@ -874,7 +874,7 @@ template< typename DCTraits, typename TDS > bool Delaunay_triangulation ::is_valid(bool verbose, int level) const -{ +{ if (!Base::is_valid(verbose, level)) return false; @@ -885,16 +885,16 @@ Delaunay_triangulation cit != finite_full_cells_end() ; ++cit ) { Full_cell_const_handle ch = cit.base(); - for(int i = 0; i < dim+1 ; ++i ) + for(int i = 0; i < dim+1 ; ++i ) { // If the i-th neighbor is not an infinite cell - Vertex_handle opposite_vh = + Vertex_handle opposite_vh = ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); if (!is_infinite(opposite_vh)) { - Side_of_oriented_sphere_d side = + Side_of_oriented_sphere_d side = geom_traits().side_of_oriented_sphere_d_object(); - if (side(Point_const_iterator(ch->vertices_begin()), + if (side(Point_const_iterator(ch->vertices_begin()), Point_const_iterator(ch->vertices_end()), opposite_vh->point()) == ON_BOUNDED_SIDE) { diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 0f12fdfcc6c..3ea884d60e6 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -94,7 +94,7 @@ input_point(std::istream & is, const Traits &traits, P & p) { typedef typename Traits::FT FT; std::vector coords; - + std::string line; for(;;) { @@ -125,7 +125,7 @@ operator>>(std::istream &is, typename Wrap::Point_d & p) typedef typename Wrap::Point_d P; typedef typename K::FT FT; std::vector coords; - + std::string line; for(;;) { @@ -175,7 +175,7 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) template < class GT, class TDS > std::ostream & -export_triangulation_to_off(std::ostream & os, +export_triangulation_to_off(std::ostream & os, const Triangulation & tr, bool in_3D_export_surface_only = false) { @@ -188,7 +188,7 @@ export_triangulation_to_off(std::ostream & os, typedef typename Tr::Full_cell_const_iterator Full_cell_iterator; typedef typename Tr::Full_cell Full_cell; typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator; - + if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3) { std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3."; @@ -199,11 +199,11 @@ export_triangulation_to_off(std::ostream & os, size_t n = tr.number_of_vertices(); std::stringstream output; - + // write the vertices std::map index_of_vertex; int i = 0; - for(Finite_vertex_iterator it = tr.finite_vertices_begin(); + for(Finite_vertex_iterator it = tr.finite_vertices_begin(); it != tr.finite_vertices_end(); ++it, ++i) { Triangulation_IO::output_point(output, tr.geom_traits(), it->point()); @@ -213,7 +213,7 @@ export_triangulation_to_off(std::ostream & os, index_of_vertex[it.base()] = i; } CGAL_assertion( i == n ); - + size_t number_of_triangles = 0; if (tr.maximal_dimension() == 2) { @@ -248,7 +248,7 @@ export_triangulation_to_off(std::ostream & os, output << index_of_vertex[*vit] << " "; } output << std::endl; - ++number_of_triangles; + ++number_of_triangles; } } } @@ -284,7 +284,7 @@ export_triangulation_to_off(std::ostream & os, } os << "OFF \n" - << n << " " + << n << " " << number_of_triangles << " 0\n" << output.str(); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index c9da2cdfb25..40196f01feb 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -44,17 +44,17 @@ class Regular_triangulation >::type> { typedef Regular_triangulation_euclidean_traits RTTraits; - typedef typename RTTraits::Dimension Maximal_dimension_; + typedef typename RTTraits::Dimension Maximal_dimension_; typedef typename Default::Get< - TDS_, + TDS_, Triangulation_data_structure< - Maximal_dimension_, - Triangulation_vertex, - Triangulation_full_cell - > >::type TDS; - typedef Triangulation Base; + Maximal_dimension_, + Triangulation_vertex, + Triangulation_full_cell + > >::type TDS; + typedef Triangulation Base; typedef Regular_triangulation Self; - + typedef typename RTTraits::Orientation_d Orientation_d; typedef typename RTTraits::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; typedef typename RTTraits::In_flat_power_side_of_power_sphere_d @@ -156,7 +156,7 @@ private: }; public: - + // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS Regular_triangulation(int dim, const Geom_traits &k = Geom_traits()) @@ -165,12 +165,12 @@ public: } // With this constructor, - // the user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension // (= preset_flat_orientation_.first) // It it used by the dark triangulations created by DT::remove Regular_triangulation( - int dim, + int dim, const std::pair &preset_flat_orientation, const Geom_traits &k = Geom_traits()) : Base(dim, preset_flat_orientation, k) @@ -185,8 +185,8 @@ public: Power_side_of_power_sphere_for_non_maximal_dim_d power_side_of_power_sphere_for_non_maximal_dim_predicate() const { return Power_side_of_power_sphere_for_non_maximal_dim_d ( - flat_orientation_, - geom_traits().construct_flat_orientation_d_object(), + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), geom_traits().in_flat_power_side_of_power_sphere_d_object() ); } @@ -246,13 +246,13 @@ public: return number_of_vertices() - n; } - Vertex_handle insert(const Weighted_point &, - const Locate_type, - const Face &, - const Facet &, + Vertex_handle insert(const Weighted_point &, + const Locate_type, + const Face &, + const Facet &, const Full_cell_handle); - Vertex_handle insert(const Weighted_point & p, + Vertex_handle insert(const Weighted_point & p, const Full_cell_handle start = Full_cell_handle()) { Locate_type lt; @@ -272,14 +272,14 @@ public: Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, const Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle()); - - Vertex_handle insert_if_in_star(const Weighted_point &, - const Vertex_handle, - const Locate_type, - const Face &, - const Facet &, + + Vertex_handle insert_if_in_star(const Weighted_point &, + const Vertex_handle, + const Locate_type, + const Face &, + const Facet &, const Full_cell_handle); - + Vertex_handle insert_if_in_star( const Weighted_point & p, const Vertex_handle star_center, const Full_cell_handle start = Full_cell_handle()) @@ -292,7 +292,7 @@ public: } Vertex_handle insert_if_in_star( - const Weighted_point & p, const Vertex_handle star_center, + const Weighted_point & p, const Vertex_handle star_center, const Vertex_handle hint) { CGAL_assertion( Vertex_handle() != hint ); @@ -348,7 +348,7 @@ public: Orientation o = ori_( boost::make_transform_iterator(s->vertices_begin(), spivi), - boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, spivi)); if( POSITIVE == o ) @@ -377,9 +377,9 @@ public: return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f))); } }; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY - + bool is_valid(bool verbose = false, int level = 0) const; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MISC @@ -390,10 +390,10 @@ public: } private: - + template bool - does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end, + does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end, Vertex_handle vh) const { // Check all vertices @@ -412,7 +412,7 @@ private: template void - process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, + process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, OutputIterator vertices_out) const { // Get all vertices @@ -432,10 +432,10 @@ private: } } - + template void - process_cz_vertices_after_insertion(InputIterator vertices_begin, + process_cz_vertices_after_insertion(InputIterator vertices_begin, InputIterator vertices_end) { // Get all vertices @@ -463,14 +463,14 @@ private: Conflict_traversal_pred_in_subspace; typedef Conflict_traversal_predicate Conflict_traversal_pred_in_fullspace; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MEMBER VARIABLES std::vector m_hidden_points; }; // class Regular_triangulation -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // FUNCTIONS THAT ARE MEMBER METHODS: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS @@ -504,8 +504,8 @@ Regular_triangulation left = left->neighbor(1); CGAL_assertion( 1 == left->index(v) ); Full_cell_handle right = left->neighbor(0); - tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); - set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); tds().delete_vertex(v); tds().delete_full_cell(right); return left; @@ -536,8 +536,8 @@ Regular_triangulation typedef Triangulation_full_cell< Geom_traits, internal::Triangulation::Dark_full_cell_data > Dark_full_cell_base; - typedef Triangulation_data_structure Dark_tds; typedef Regular_triangulation Dark_triangulation; @@ -598,7 +598,7 @@ Regular_triangulation { int v_idx = (*it)->index(v); tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); - } + } // Make the handles to infinite full cells searchable infinite_simps.make_searchable(); // Then, modify the neighboring relation @@ -648,7 +648,7 @@ Regular_triangulation typedef typename Base::template Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); - + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); // Make the dark simplices in the conflict zone searchable conflict_zone.make_searchable(); @@ -673,8 +673,8 @@ Regular_triangulation dark_incident_s.clear(); dark_out = std::back_inserter(dark_incident_s); dark_side.tds().incident_full_cells(dark_v, dark_out); - for(typename Dark_full_cells::iterator it = dark_incident_s.begin(); - it != dark_incident_s.end(); + for(typename Dark_full_cells::iterator it = dark_incident_s.begin(); + it != dark_incident_s.end(); ++it) { (*it)->data().count_ += 1; @@ -748,7 +748,7 @@ Regular_triangulation int li = light_s->index(dark_s->vertex(di)->data()); Rotor light_r(light_s, li, light_i); typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); - + while( simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r))) ) light_r = rotate_rotor(light_r); @@ -815,7 +815,7 @@ Regular_triangulation geom_traits().point_weight_d_object(); if (pw(p) == pw(v->point())) - return v; + return v; // If dim == 0 and the new point has a bigger weight, // we just replace the point, and the former point gets hidden else if (current_dimension() == 0) @@ -823,11 +823,11 @@ Regular_triangulation if (pw(p) > pw(v->point())) { m_hidden_points.push_back(v->point()); - v->set_point(p); - return v; - } + v->set_point(p); + return v; + } // Otherwise, the new point is hidden - else + else { m_hidden_points.push_back(p); return Vertex_handle(); @@ -838,7 +838,7 @@ Regular_triangulation // !NO break here! } default: - return insert_in_conflicting_cell(p, s); + return insert_in_conflicting_cell(p, s); } } @@ -874,7 +874,7 @@ Regular_triangulation && inf_v_index == 0) { inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); - } + } else { inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); @@ -894,9 +894,9 @@ Regular_triangulation template< typename Traits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation -::insert_if_in_star(const Weighted_point & p, +::insert_if_in_star(const Weighted_point & p, const Vertex_handle star_center, - const Locate_type lt, const Face & f, const Facet & ft, + const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) { switch( lt ) @@ -910,23 +910,23 @@ Regular_triangulation typename RTTraits::Point_weight_d pw = geom_traits().point_weight_d_object(); if (pw(p) == pw(v->point())) - return v; + return v; // If dim == 0 and the new point has a bigger weight, // we replace the point else if (current_dimension() == 0) - { + { if (pw(p) > pw(v->point())) v->set_point(p); else return v; - } + } // Otherwise, we apply the "normal" algorithm // !NO break here! - } + } default: - return insert_in_conflicting_cell(p, s, star_center); - } + return insert_in_conflicting_cell(p, s, star_center); + } return Vertex_handle(); } @@ -934,7 +934,7 @@ Regular_triangulation template< typename Traits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation -::insert_in_conflicting_cell(const Weighted_point & p, +::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s, const Vertex_handle only_if_this_vertex_is_in_the_cz) { @@ -955,10 +955,10 @@ Regular_triangulation cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); - + // Check if the CZ contains "only_if_this_vertex_is_in_the_cz" if (only_if_this_vertex_is_in_the_cz != Vertex_handle() - && !does_cell_range_contain_vertex(cs.begin(), cs.end(), + && !does_cell_range_contain_vertex(cs.begin(), cs.end(), only_if_this_vertex_is_in_the_cz)) { return Vertex_handle(); @@ -967,7 +967,7 @@ Regular_triangulation // Otherwise, proceed with the insertion std::vector cz_vertices; cz_vertices.reserve(64); - process_conflict_zone(cs.begin(), cs.end(), + process_conflict_zone(cs.begin(), cs.end(), std::back_inserter(cz_vertices)); Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft); @@ -1048,8 +1048,8 @@ Regular_triangulation if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), + *this, p, + coaffine_orientation_predicate(), power_side_of_power_sphere_for_non_maximal_dim_predicate()); return c(s); } @@ -1072,8 +1072,8 @@ Regular_triangulation if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), + *this, p, + coaffine_orientation_predicate(), power_side_of_power_sphere_for_non_maximal_dim_predicate()); Conflict_traversal_pred_in_subspace tp(*this, c); return tds().gather_full_cells(s, tp, out); @@ -1094,7 +1094,7 @@ template< typename Traits, typename TDS > bool Regular_triangulation ::is_valid(bool verbose, int level) const -{ +{ if (!Base::is_valid(verbose, level)) return false; @@ -1105,16 +1105,16 @@ Regular_triangulation cit != finite_full_cells_end() ; ++cit ) { Full_cell_const_handle ch = cit.base(); - for(int i = 0; i < dim+1 ; ++i ) + for(int i = 0; i < dim+1 ; ++i ) { // If the i-th neighbor is not an infinite cell - Vertex_handle opposite_vh = + Vertex_handle opposite_vh = ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); if (!is_infinite(opposite_vh)) { Power_side_of_power_sphere_d side = geom_traits().power_side_of_power_sphere_d_object(); - if (side(Point_const_iterator(ch->vertices_begin()), + if (side(Point_const_iterator(ch->vertices_begin()), Point_const_iterator(ch->vertices_end()), opposite_vh->point()) == ON_POSITIVE_SIDE) { From ec16393b39dcd82c9b6fc474b4520b2dd9ce1ce2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 1 Jun 2016 14:42:17 +0200 Subject: [PATCH 449/487] Fix Linux compilation error --- Triangulation/include/CGAL/Delaunay_triangulation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 49a8210b649..5c0afff4744 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -881,8 +881,8 @@ Delaunay_triangulation int dim = current_dimension(); if (dim == maximal_dimension()) { - for (Finite_full_cell_const_iterator cit = finite_full_cells_begin() ; - cit != finite_full_cells_end() ; ++cit ) + for (Finite_full_cell_const_iterator cit = this->finite_full_cells_begin() ; + cit != this->finite_full_cells_end() ; ++cit ) { Full_cell_const_handle ch = cit.base(); for(int i = 0; i < dim+1 ; ++i ) From 7ce61ee678cc7d1483e8663a139f89d7edbfee5a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 15:38:44 +0100 Subject: [PATCH 450/487] operator>> for Vector_d --- .../CGAL/IO/Triangulation_off_ostream.h | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 3ea884d60e6..892819ab3b2 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -173,6 +173,32 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) return is; } +// TODO: test if the stream is binary or text? +template +std::istream & +operator>>(std::istream &is, typename Wrap::Vector_d & v) +{ + typedef typename Wrap::Vector_d V; + typedef typename K::FT FT; + std::vector coords; + + std::string line; + for (;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + while (line_sstr >> temp) + coords.push_back(temp); + + v = V(coords.begin(), coords.end()); + return is; +} + template < class GT, class TDS > std::ostream & export_triangulation_to_off(std::ostream & os, From 5e03101540e38c26e13fa37e2c0477a92f087113 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 6 Jul 2016 11:06:26 +0200 Subject: [PATCH 451/487] Add concept/model relationship --- Kernel_d/doc/Kernel_d/CGAL/Epick_d.h | 1 + .../doc/Spatial_searching/Concepts/SearchTraits.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h index 3a14e30fedf..5d125fb1a61 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h @@ -38,6 +38,7 @@ icc 15 work. \cgalModels `Kernel_d` \cgalModels `DelaunayTriangulationTraits` \cgalModels `RegularTriangulationTraits` +\cgalModels `SearchTraits` \sa `CGAL::Cartesian_d` \sa `CGAL::Homogeneous_d` diff --git a/Spatial_searching/doc/Spatial_searching/Concepts/SearchTraits.h b/Spatial_searching/doc/Spatial_searching/Concepts/SearchTraits.h index a19ffd30883..0200b1feea6 100644 --- a/Spatial_searching/doc/Spatial_searching/Concepts/SearchTraits.h +++ b/Spatial_searching/doc/Spatial_searching/Concepts/SearchTraits.h @@ -6,7 +6,8 @@ The concept `SearchTraits` defines the requirements for the template parameter of the search classes. \cgalHasModel `CGAL::Cartesian_d` -\cgalHasModel `CGAL::Homogeneous_d` +\cgalHasModel `CGAL::Homogeneous_d` +\cgalHasModel `CGAL::Epick_d` \cgalHasModel `CGAL::Search_traits_2` \cgalHasModel `CGAL::Search_traits_3` \cgalHasModel `CGAL::Search_traits_d` From 3d8d601b284affcf20ad9a6f787098dab95621e4 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 7 Jul 2016 19:32:51 +0200 Subject: [PATCH 452/487] Construct_center_d alias for RangeSearchTraits --- NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h | 1 + 1 file changed, 1 insertion(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index 327dd0698c8..f7f89413b7a 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -163,6 +163,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Side_of_bounded_sphere_d; typedef typename Get_functor::type Center_of_sphere_d; + typedef Center_of_sphere_d Construct_center_d; // RangeSearchTraits typedef typename Get_functor::type Construct_circumcenter_d; typedef typename Get_functor::type Value_at_d; typedef typename Get_functor::type Point_of_sphere_d; From 9f2155da93d93cb19baebfd58f2f6c2fc681d354 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 28 Jul 2016 12:17:14 +0200 Subject: [PATCH 453/487] Remove advanced on collapse_face --- Triangulation/doc/Triangulation/CGAL/Triangulation.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index 1175a96cb26..bef3c1ffae9 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -514,13 +514,11 @@ Face & f, Vertex_handle hint) const; /// @{ /*! -\cgalAdvancedBegin Contracts the `Face f` to a single vertex at position `p`. Returns a handle to that vertex. \pre The boundary of the union of full cells incident to `f` must be a triangulation of a sphere of dimension `tr`.`current_dimension()`). -\cgalAdvancedEnd */ Vertex_handle collapse_face(const Point & p, const Face & f); From 88b86f96f4a5b697626bc02d4a05d8354608545b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 29 Jul 2016 12:06:01 +0200 Subject: [PATCH 454/487] Add concept/model relationship --- Kernel_d/doc/Kernel_d/CGAL/Epick_d.h | 1 + .../doc/Spatial_searching/Concepts/RangeSearchTraits.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h index 5d125fb1a61..585ffc20773 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h @@ -39,6 +39,7 @@ icc 15 work. \cgalModels `DelaunayTriangulationTraits` \cgalModels `RegularTriangulationTraits` \cgalModels `SearchTraits` +\cgalModels `RangeSearchTraits` \sa `CGAL::Cartesian_d` \sa `CGAL::Homogeneous_d` diff --git a/Spatial_searching/doc/Spatial_searching/Concepts/RangeSearchTraits.h b/Spatial_searching/doc/Spatial_searching/Concepts/RangeSearchTraits.h index 4aec9382492..15094215001 100644 --- a/Spatial_searching/doc/Spatial_searching/Concepts/RangeSearchTraits.h +++ b/Spatial_searching/doc/Spatial_searching/Concepts/RangeSearchTraits.h @@ -10,6 +10,7 @@ range search queries in a model of `SpatialTree`. \cgalHasModel `CGAL::Cartesian_d` \cgalHasModel `CGAL::Homogeneous_d` +\cgalHasModel `CGAL::Epick_d` \cgalHasModel `CGAL::Search_traits_2` \cgalHasModel `CGAL::Search_traits_3` From 90de002af76b36ea0b47df1990af53c095372019 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 29 Jul 2016 12:13:56 +0200 Subject: [PATCH 455/487] Remove duplicated code --- NewKernel_d/test/NewKernel_d/Epick_d.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index d0f8c6e9b40..515cbdf380e 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -396,16 +396,6 @@ void test2(){ assert(cc(tr,0)==4); assert(cc(tr,1)==5); - WP tw[]={cwp(cp(5,0),1.5),cwp(cp(2,std::sqrt(3)),1),cwp(cp(2,-std::sqrt(3)),1)}; - WP xw=pc(tw+0,tw+3); - assert(abs(pod(xw,tw[0]))<.0001); - assert(abs(pod(xw,tw[1]))<.0001); - assert(abs(pod(xw,tw[2]))<.0001); - assert(pdw(xw)[0]<2.95); - assert(pdw(xw)[0]>2.5); - assert(pw(xw)<2.95); - assert(pw(xw)>2.5); - Sp un1; CGAL_USE(un1); H un2; CGAL_USE(un2); S un3; CGAL_USE(un3); From bdf213167f71d3febc9534ba9342c04ba34cd29e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 6 Sep 2016 14:34:49 +0200 Subject: [PATCH 456/487] Better section title --- Triangulation/doc/Triangulation/Triangulation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 8b3953860b0..ad97e58d0f2 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -72,7 +72,7 @@ and additional requirements: simplices (the empty set counts). -## What's in this Package? ## +## What is Provided in this Package? ## This \cgal package provides four main classes for creating and manipulating triangulations. From 66c29aecc25c55887e1c6d609b45c248f38c5471 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 6 Sep 2016 15:06:36 +0200 Subject: [PATCH 457/487] Doc and comment fixes --- Triangulation/doc/Triangulation/Triangulation.txt | 7 +++---- .../examples/Triangulation/regular_triangulation.cpp | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index ad97e58d0f2..6e35ea2e67b 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -447,8 +447,7 @@ The class `CGAL::Regular_triangulation` and represents regular triangulations. -Regular triangulations are similar to Delaunay triangulations, but -with weighted points. +Regular triangulations are also known as weighted Delaunay triangulations. Let \f$ {S}^{(w)}\f$ be a set of weighted points in \f$ \mathbb{R}^D\f$. Let \f$ {p}^{(w)}=(p,w_p), p\in\mathbb{R}^D, w_p\in\mathbb{R}\f$ and @@ -478,7 +477,7 @@ Note that as a result, some points can be hidden and do not result in vertices in the triangulation. Those points are discarded and cannot be retrieved. A weighted point `p` is said to be in conflict -with a cell `c` if it has a negative power distance to the power sphere of `c`. +with a simplex `s` if it has a negative power distance to the power sphere of `s`. Regular triangulations support insertion of weighted points, and location of a query point inside the triangulation. @@ -516,7 +515,7 @@ set of points. In the worst case, the expected complexity is run on \f$ n \f$ random points, the cost of inserting one point is \f$ O(n^{1/d}) \f$. -We provide below (Figure \cgalFigureRef{Triangulationfigbenchmarks100}, +We provide below (\cgalFigureRef{Triangulationfigbenchmarks100}, \cgalFigureRef{Triangulationfigbenchmarks1000} and \cgalFigureRef{triangulationfigbenchmarkchart}) the performance of the Delaunay triangulation on randomly distributed points. diff --git a/Triangulation/examples/Triangulation/regular_triangulation.cpp b/Triangulation/examples/Triangulation/regular_triangulation.cpp index a8a917db17e..aa70e175d55 100644 --- a/Triangulation/examples/Triangulation/regular_triangulation.cpp +++ b/Triangulation/examples/Triangulation/regular_triangulation.cpp @@ -16,7 +16,7 @@ typedef T::Weighted_point Weighted_point; int main() { - // Instanciate a random point generator + // Instantiate a random point generator CGAL::Random rng(0); typedef CGAL::Random_points_in_cube_d Random_points_iterator; Random_points_iterator rand_it(D, 1.0, rng); From 6988c1867d01721b9fd3a7e44950aeeb9861e1e0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 6 Sep 2016 15:18:35 +0200 Subject: [PATCH 458/487] Move paragraph --- Triangulation/doc/Triangulation/Triangulation.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 6e35ea2e67b..eaae9580c62 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -563,6 +563,11 @@ Running time wrt. number of maximal simplices, for dimensions for 2 to 12. \section TriangulationSecDesign Design and Implementation History +Starting with the version 2.3 of \cgal, a package written by Susan Hert and Michael Seel +was the first able to deal with triangulation and convex hulls in arbitrary +dimension. It is deprecated since the version 4.6 of \cgal and this package should be used +instead. + This package is heavily inspired by the works of Monique Teillaud and Sylvain Pion (`Triangulation_3`) and Mariette Yvinec (`Triangulation_2`). @@ -574,10 +579,6 @@ Clément Jamin's work was supported by the Advanced Grant of the European Research Council GUDHI (Geometric Understanding in Higher Dimensions). -Starting with the version 2.3 of \cgal, a package written by Susan Hert and Michael Seel -was the first able to deal with triangulation and convex hulls in arbitrary -dimension. It is deprecated since the version 4.6 of \cgal and this package should be used -instead. */ } /* namespace CGAL */ From ded46066c1cb852cd28ec1617eda2ddc76eaa1bf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 6 Sep 2016 15:23:28 +0200 Subject: [PATCH 459/487] Fix identation --- .../include/CGAL/Regular_triangulation.h | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 40196f01feb..fa73788cef3 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -598,7 +598,7 @@ Regular_triangulation { int v_idx = (*it)->index(v); tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); - } + } // Make the handles to infinite full cells searchable infinite_simps.make_searchable(); // Then, modify the neighboring relation @@ -815,7 +815,7 @@ Regular_triangulation geom_traits().point_weight_d_object(); if (pw(p) == pw(v->point())) - return v; + return v; // If dim == 0 and the new point has a bigger weight, // we just replace the point, and the former point gets hidden else if (current_dimension() == 0) @@ -823,11 +823,11 @@ Regular_triangulation if (pw(p) > pw(v->point())) { m_hidden_points.push_back(v->point()); - v->set_point(p); - return v; - } + v->set_point(p); + return v; + } // Otherwise, the new point is hidden - else + else { m_hidden_points.push_back(p); return Vertex_handle(); @@ -838,7 +838,7 @@ Regular_triangulation // !NO break here! } default: - return insert_in_conflicting_cell(p, s); + return insert_in_conflicting_cell(p, s); } } @@ -874,7 +874,7 @@ Regular_triangulation && inf_v_index == 0) { inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); - } + } else { inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); @@ -910,16 +910,16 @@ Regular_triangulation typename RTTraits::Point_weight_d pw = geom_traits().point_weight_d_object(); if (pw(p) == pw(v->point())) - return v; + return v; // If dim == 0 and the new point has a bigger weight, // we replace the point else if (current_dimension() == 0) - { + { if (pw(p) > pw(v->point())) v->set_point(p); else return v; - } + } // Otherwise, we apply the "normal" algorithm // !NO break here! @@ -997,7 +997,7 @@ Regular_triangulation points[i] = &(s->vertex(i)->point()); points[i] = &p; std::sort(points.begin(), points.end(), - internal::Triangulation::Compare_points_for_perturbation(*this)); + internal::Triangulation::Compare_points_for_perturbation(*this)); typename Points::const_reverse_iterator cut_pt = points.rbegin(); Points test_points; while( cut_pt != points.rend() ) From fcb7a8287478e3501f7bd22907b41afd1fb99d67 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 6 Sep 2016 16:02:36 +0200 Subject: [PATCH 460/487] Monique's review continued --- .../doc/Triangulation/CGAL/Regular_triangulation.h | 11 ++++++----- Triangulation/doc/Triangulation/Triangulation.txt | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 3f0b881c44f..8ab773a9586 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -13,9 +13,6 @@ section in the user manual for what reasonable means. \warning The removal of points is not supported yet. -A comprehensive definition of regular triangulations is available in the -User Manual. - \tparam RegularTriangulationTraits_ is the geometric traits class that provides the geometric types and predicates needed by regular triangulations. `RegularTriangulationTraits_` must be a model of the concept @@ -32,7 +29,7 @@ instantiated as follows:
  • `Triangulation_full_cell >`.
  • -\tparam Regular_triangulation can +`Regular_triangulation` can be defined by specifying only the first parameter, or by using the tag `CGAL::Default` as the second parameter. @@ -136,7 +133,11 @@ must lie outside the affine hull of the regular triangulation. This implies that Vertex_handle insert_outside_affine_hull(const Weighted_point & p); /*! -Inserts the point `p` in the regular triangulation. +Inserts the point `p` in the regular triangulation. `p` must be +in conflict with the second parameter `c`, which is used as a +starting point for `compute_conflict_zone`. +The function is faster than the standard `insert` function since +it does not need to call `locate`. If this insertion creates a vertex, this vertex is returned. diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index eaae9580c62..918b89b4678 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -572,7 +572,7 @@ This package is heavily inspired by the works of Monique Teillaud and Sylvain Pion (`Triangulation_3`) and Mariette Yvinec (`Triangulation_2`). The first version was written by Samuel Hornus. The final version is a joint -work by Samuel Hornus, Olivier Devillers and Clément Jamin. In 2015, Clément +work by Samuel Hornus, Olivier Devillers and Clément Jamin. In 2017, Clément Jamin added the regular triangulations. Clément Jamin's work was supported by the From c709bd54f0f057b22d633592b226df4419961448 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 7 Sep 2016 15:51:12 +0200 Subject: [PATCH 461/487] Regular_triangulation_euclidean_traits => Regular_triangulation_traits_adapter --- .../doc/Triangulation/CGAL/Regular_triangulation.h | 8 ++++---- ...aits.h => Regular_triangulation_traits_adapter.h} | 6 +++--- .../doc/Triangulation/PackageDescription.txt | 2 +- Triangulation/include/CGAL/Regular_triangulation.h | 12 ++++++------ ...aits.h => Regular_triangulation_traits_adapter.h} | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) rename Triangulation/doc/Triangulation/CGAL/{Regular_triangulation_euclidean_traits.h => Regular_triangulation_traits_adapter.h} (86%) rename Triangulation/include/CGAL/{Regular_triangulation_euclidean_traits.h => Regular_triangulation_traits_adapter.h} (97%) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 8ab773a9586..11c09c053a2 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -25,8 +25,8 @@ defaults to `Triangulation_data_structure` whose template parameters are instantiated as follows:
    • `RegularTriangulationTraits_::Dimension`
    • -
    • `Triangulation_vertex >`
    • -
    • `Triangulation_full_cell >`.
    • +
    • `Triangulation_vertex >`
    • +
    • `Triangulation_full_cell >`.
    `Regular_triangulation` can @@ -35,12 +35,12 @@ tag `CGAL::Default` as the second parameter. \sa `Delaunay_triangulation` \sa `Triangulation_data_structure` -\sa `Regular_triangulation_euclidean_traits` +\sa `Regular_triangulation_traits_adapter` */ template< typename RegularTriangulationTraits_, typename TriangulationDataStructure_ > class Regular_triangulation - : public Triangulation, TriangulationDataStructure_> + : public Triangulation, TriangulationDataStructure_> { public: diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_traits_adapter.h similarity index 86% rename from Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h rename to Triangulation/doc/Triangulation/CGAL/Regular_triangulation_traits_adapter.h index 049b1d379df..c1654d8efb0 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation_traits_adapter.h @@ -4,7 +4,7 @@ namespace CGAL { /*! \ingroup PkgTriangulationsTraitsClasses -The class `Regular_triangulation_euclidean_traits` is used internally by the +The class `Regular_triangulation_traits_adapter` is used internally by the class `Regular_triangulation` to wrap its first template parameter (`RegularTriangulationTraits_`) so that the base class `Triangulation` manipulates weighted points instead @@ -29,7 +29,7 @@ ignoring the weights. */ template -class Regular_triangulation_euclidean_traits : public K { +class Regular_triangulation_traits_adapter : public K { public: /// \name Types @@ -53,7 +53,7 @@ public: /*! The default constructor. */ - Regular_triangulation_euclidean_traits(); + Regular_triangulation_traits_adapter(); /// @} diff --git a/Triangulation/doc/Triangulation/PackageDescription.txt b/Triangulation/doc/Triangulation/PackageDescription.txt index 4937cbba3e1..b3bf73dd86f 100644 --- a/Triangulation/doc/Triangulation/PackageDescription.txt +++ b/Triangulation/doc/Triangulation/PackageDescription.txt @@ -112,7 +112,7 @@ The latter two concepts are also abbreviated respectively as `TrVertex` and `TrF ## Traits Classes ## -- `CGAL::Regular_triangulation_euclidean_traits` +- `CGAL::Regular_triangulation_traits_adapter` ## Enums ## diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index fa73788cef3..8d0a023a602 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include @@ -33,17 +33,17 @@ namespace CGAL { template< typename Traits_, typename TDS_ = Default > class Regular_triangulation : public Triangulation< - Regular_triangulation_euclidean_traits, + Regular_triangulation_traits_adapter, typename Default::Get< TDS_, Triangulation_data_structure< - typename Regular_triangulation_euclidean_traits::Dimension, - Triangulation_vertex >, - Triangulation_full_cell > + typename Regular_triangulation_traits_adapter::Dimension, + Triangulation_vertex >, + Triangulation_full_cell > > >::type> { - typedef Regular_triangulation_euclidean_traits RTTraits; + typedef Regular_triangulation_traits_adapter RTTraits; typedef typename RTTraits::Dimension Maximal_dimension_; typedef typename Default::Get< TDS_, diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h similarity index 97% rename from Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h rename to Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h index 0275a842d48..f88a32ba417 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h @@ -17,8 +17,8 @@ // // Author(s) : Clement Jamin -#ifndef CGAL_REGULAR_TRIANGULATION_EUCLIDEAN_TRAITS_H -#define CGAL_REGULAR_TRIANGULATION_EUCLIDEAN_TRAITS_H +#ifndef CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H +#define CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H #include @@ -35,7 +35,7 @@ namespace CGAL { // This way, `Triangulation` works perfectly well with weighted points. template -class Regular_triangulation_euclidean_traits +class Regular_triangulation_traits_adapter : public K { public: @@ -285,4 +285,4 @@ public: } //namespace CGAL -#endif // CGAL_REGULAR_TRIANGULATION_EUCLIDEAN_TRAITS_H +#endif // CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H From ef03b187c3a7d01c81905984839f43f00fadc258 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 7 Sep 2016 16:28:21 +0200 Subject: [PATCH 462/487] Undocumented 2 functions --- .../CGAL/Delaunay_triangulation.h | 21 +---------- .../CGAL/Regular_triangulation.h | 35 ------------------- .../include/CGAL/Delaunay_triangulation.h | 20 ++++++++++- .../include/CGAL/Regular_triangulation.h | 33 +++++++++++++++++ 4 files changed, 53 insertions(+), 56 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h index 073654e453e..ef86da814a1 100644 --- a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h @@ -124,13 +124,11 @@ value of `lt`:
    `OUTSIDE_AFFINE_HULL`
    Point `p` is inserted so as to increase the current dimension of the Delaunay -triangulation. The method `dt`.`insert_outside_affine_hull()` is called. +triangulation.
    `ON_VERTEX`
    The position of the vertex `v` described by `f` is set to `p`. `v` is returned.
    Anything else
    The point `p` is inserted. the full cell `c` is assumed to be in conflict with `p`. -(Roughly speaking, the method `dt`.`insert_in_conflicting_cell()` -is called.)
    The parameters `lt`, `f`, `ft` and `c` must be consistent with the localization of point `p` in the @@ -140,23 +138,6 @@ Delaunay triangulation e.g. by a call to Vertex_handle insert(const Point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle c); -/*! -Inserts the point `p` in the Delaunay triangulation. Returns a handle to the -(possibly newly created) vertex at that position. -\pre The point `p` -must lie outside the affine hull of the Delaunay triangulation. This implies that -`dt`.`current_dimension()` must be less than `dt`.`maximal_dimension()`. -*/ -Vertex_handle insert_outside_affine_hull(const Point & p); - -/*! -Inserts the point `p` in the Delaunay triangulation. Returns a handle to the -(possibly newly created) vertex at that position. -\pre The point `p` must be in conflict with the full cell `c`. -*/ -Vertex_handle insert_in_conflicting_cell(const Point & p, const -Full_cell_handle c); - /// @} /// \name Queries diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 11c09c053a2..bf1b463770d 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -123,41 +123,6 @@ type `Weighted_point`. template< typename ForwardIterator > std::ptrdiff_t insert(ForwardIterator s, ForwardIterator e); -/*! -Inserts the point `p` in the regular triangulation. Returns a handle to the -newly created vertex at that position. -\pre The point `p` -must lie outside the affine hull of the regular triangulation. This implies that -`rt`.`current_dimension()` must be smaller than `rt`.`maximal_dimension()`. -*/ -Vertex_handle insert_outside_affine_hull(const Weighted_point & p); - -/*! -Inserts the point `p` in the regular triangulation. `p` must be -in conflict with the second parameter `c`, which is used as a -starting point for `compute_conflict_zone`. -The function is faster than the standard `insert` function since -it does not need to call `locate`. - -If this insertion creates a vertex, this vertex is returned. - -If `p` coincides with an existing vertex and has a greater weight, -then the existing weighted point becomes hidden and `p` replaces it as vertex -of the triangulation. - -If `p` coincides with an already existing vertex (both point and -weights being equal), then this vertex is returned and the triangulation -remains unchanged. - -Otherwise if `p` does not appear as a vertex of the triangulation, -then it is stored as a hidden point and this method returns the default -constructed handle. - -\pre The point `p` must be in conflict with the full cell `c`. -*/ -Vertex_handle insert_in_conflicting_cell(const Weighted_point & p, const -Full_cell_handle c); - /// @} /// \name Queries diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 5c0afff4744..8ade3213d8a 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -697,6 +697,15 @@ Delaunay_triangulation } } +/* +[Undocumented function] + +Inserts the point `p` in the Delaunay triangulation. Returns a handle to the +(possibly newly created) vertex at that position. +\pre The point `p` +must lie outside the affine hull of the Delaunay triangulation. This implies that +`dt`.`current_dimension()` must be less than `dt`.`maximal_dimension()`. +*/ template< typename DCTraits, typename TDS > typename Delaunay_triangulation::Vertex_handle Delaunay_triangulation @@ -731,7 +740,7 @@ Delaunay_triangulation { inf_v_cell->swap_vertices( current_dimension() - 1, current_dimension()); - } + } // Otherwise, let's find the right infinite cell else { @@ -751,11 +760,20 @@ Delaunay_triangulation return v; } +/*! +[Undocumented function] + +Inserts the point `p` in the Delaunay triangulation. Returns a handle to the +(possibly newly created) vertex at that position. +\pre The point `p` must be in conflict with the full cell `c`. +*/ template< typename DCTraits, typename TDS > typename Delaunay_triangulation::Vertex_handle Delaunay_triangulation ::insert_in_conflicting_cell(const Point & p, const Full_cell_handle s) { + CGAL_precondition(is_in_conflict(p, s)); + // for storing conflicting full_cells. typedef std::vector Full_cell_h_vector; CGAL_STATIC_THREAD_LOCAL_VARIABLE(Full_cell_h_vector,cs,0); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 8d0a023a602..349d4b0f81c 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -842,6 +842,13 @@ Regular_triangulation } } +/* +Inserts the point `p` in the regular triangulation. Returns a handle to the +newly created vertex at that position. +\pre The point `p` +must lie outside the affine hull of the regular triangulation. This implies that +`rt`.`current_dimension()` must be smaller than `rt`.`maximal_dimension()`. +*/ template< typename Traits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation @@ -931,6 +938,32 @@ Regular_triangulation return Vertex_handle(); } +/* +[Undocumented function] + +Inserts the point `p` in the regular triangulation. `p` must be +in conflict with the second parameter `c`, which is used as a +starting point for `compute_conflict_zone`. +The function is faster than the standard `insert` function since +it does not need to call `locate`. + +If this insertion creates a vertex, this vertex is returned. + +If `p` coincides with an existing vertex and has a greater weight, +then the existing weighted point becomes hidden and `p` replaces it as vertex +of the triangulation. + +If `p` coincides with an already existing vertex (both point and +weights being equal), then this vertex is returned and the triangulation +remains unchanged. + +Otherwise if `p` does not appear as a vertex of the triangulation, +then it is stored as a hidden point and this method returns the default +constructed handle. + +\pre The point `p` must be in conflict with the full cell `c`. +*/ + template< typename Traits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation From 6102307e861cf810c7e8134fc563a822ccb4555d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 7 Sep 2016 16:56:54 +0200 Subject: [PATCH 463/487] Add reference to paper --- Documentation/doc/biblio/geom.bib | 14 ++++++++++++++ Triangulation/doc/Triangulation/Triangulation.txt | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/doc/biblio/geom.bib b/Documentation/doc/biblio/geom.bib index b30754c32f3..c16a61712ec 100644 --- a/Documentation/doc/biblio/geom.bib +++ b/Documentation/doc/biblio/geom.bib @@ -151968,3 +151968,17 @@ pages = {179--189} year={2007}, organization={Wiley Online Library} } + +@inproceedings{boissonnat2009Delaunay, + TITLE = {{Incremental construction of the Delaunay graph in medium dimension}}, + AUTHOR = {Boissonnat, Jean-Daniel and Devillers, Olivier OD and Hornus, Samuel}, + URL = {https://hal.inria.fr/inria-00412437}, + BOOKTITLE = {{Annual Symposium on Computational Geometry}}, + ADDRESS = {Aarhus, Denmark}, + PAGES = {208-216}, + YEAR = {2009}, + MONTH = Jun, + PDF = {https://hal.inria.fr/inria-00412437/file/socg09.pdf}, + HAL_ID = {inria-00412437}, + HAL_VERSION = {v1}, +} \ No newline at end of file diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 918b89b4678..f1e5782c2cc 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -9,7 +9,7 @@ namespace CGAL { \authors Olivier Devillers, Samuel Hornus, and Clément Jamin. This package proposes data structures and algorithms to compute -triangulations of points in any dimensions. +triangulations of points in any dimensions \cgalCite{boissonnat2009Delaunay}. The `Triangulation_data_structure` handles the combinatorial aspect of triangulations while the geometric classes `Triangulation`, `Delaunay_triangulation` and `Regular_triangulation` allow to From af35f0ead710323cc55101ab788efa0d6426a634 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 8 Sep 2016 10:59:33 +0200 Subject: [PATCH 464/487] Improve sentence --- Triangulation/doc/Triangulation/Triangulation.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index f1e5782c2cc..b4ac0504e0e 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -508,9 +508,13 @@ This simple example shows how to create a regular triangulation. \section TriangulationSecPerf Complexity and Performances -The current implementation locates points by walking in the -triangulation, and sorts the points with spatial sort to insert a -set of points. In the worst case, the expected complexity is +When inserting a set of points into a Delaunay triangulation, +the current implementation starts +by spatially sorting the points. Then, for each point to insert, +it locates it by walking in the triangulation, using the +previously inserted vertex as a "hint". Finally, the point is +inserted. +In the worst case, the expected complexity is \f$ O(n^{\lceil\frac{d}{2}\rceil}+n\log n)\f$. When the algorithm is run on \f$ n \f$ random points, the cost of inserting one point is \f$ O(n^{1/d}) \f$. From b7efa8e756d0e1dac69e9af3ea8c63634631c229 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 8 Sep 2016 11:56:49 +0200 Subject: [PATCH 465/487] Small fix --- Triangulation/doc/Triangulation/CGAL/Triangulation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index bef3c1ffae9..b43accc0214 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -17,11 +17,11 @@ incident to the infinite vertex and to an \f$ (i-1)\f$-simplex of the convex hull boundary. -\tparam `TriangulationTraits_` is the geometric traits class that provides the geometric types +\tparam TriangulationTraits_ is the geometric traits class that provides the geometric types and predicates needed by triangulations. `TriangulationTraits_` must be a model of the concept `TriangulationTraits`. -\tparam `TriangulationDataStructure_` must be a model of the concept +\tparam TriangulationDataStructure_ must be a model of the concept `TriangulationDataStructure`. This model is used to store the faces of the triangulation. The parameter `TriangulationDataStructure_` defaults to `Triangulation_data_structure` whose template parameters are instantiated as From 867e6d115892bbcef71245d050a8269b50ce1640 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 8 Sep 2016 15:52:38 +0200 Subject: [PATCH 466/487] Remove useless const --- .../include/CGAL/Delaunay_triangulation.h | 16 +++---- .../include/CGAL/Regular_triangulation.h | 44 ++++++++++--------- Triangulation/include/CGAL/Triangulation.h | 26 +++++------ 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 8ade3213d8a..071cd184f7b 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -229,8 +229,8 @@ public: } return number_of_vertices() - n; } - Vertex_handle insert(const Point &, const Locate_type, const Face &, const Facet &, const Full_cell_handle); - Vertex_handle insert(const Point & p, const Full_cell_handle start = Full_cell_handle()) + Vertex_handle insert(const Point &, Locate_type, const Face &, const Facet &, Full_cell_handle); + Vertex_handle insert(const Point & p, Full_cell_handle start = Full_cell_handle()) { Locate_type lt; Face f(maximal_dimension()); @@ -238,13 +238,13 @@ public: Full_cell_handle s = locate(p, lt, f, ft, start); return insert(p, lt, f, ft, s); } - Vertex_handle insert(const Point & p, const Vertex_handle hint) + Vertex_handle insert(const Point & p, Vertex_handle hint) { CGAL_assertion( Vertex_handle() != hint ); return insert(p, hint->full_cell()); } Vertex_handle insert_outside_affine_hull(const Point &); - Vertex_handle insert_in_conflicting_cell(const Point &, const Full_cell_handle); + Vertex_handle insert_in_conflicting_cell(const Point &, Full_cell_handle); // - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES @@ -254,7 +254,7 @@ public: Full_cell_const_handle, const OrientationPredicate &) const; template< typename OutputIterator > - Facet compute_conflict_zone(const Point &, const Full_cell_handle, OutputIterator) const; + Facet compute_conflict_zone(const Point &, Full_cell_handle, OutputIterator) const; template < typename OrientationPredicate, typename SideOfOrientedSpherePredicate > class Conflict_predicate @@ -666,7 +666,7 @@ Delaunay_triangulation template< typename DCTraits, typename TDS > typename Delaunay_triangulation::Vertex_handle Delaunay_triangulation -::insert(const Point & p, const Locate_type lt, const Face & f, const Facet &, const Full_cell_handle s) +::insert(const Point & p, Locate_type lt, const Face & f, const Facet &, Full_cell_handle s) { switch( lt ) { @@ -770,7 +770,7 @@ Inserts the point `p` in the Delaunay triangulation. Returns a handle to the template< typename DCTraits, typename TDS > typename Delaunay_triangulation::Vertex_handle Delaunay_triangulation -::insert_in_conflicting_cell(const Point & p, const Full_cell_handle s) +::insert_in_conflicting_cell(const Point & p, Full_cell_handle s) { CGAL_precondition(is_in_conflict(p, s)); @@ -867,7 +867,7 @@ template< typename DCTraits, typename TDS > template< typename OutputIterator > typename Delaunay_triangulation::Facet Delaunay_triangulation -::compute_conflict_zone(const Point & p, const Full_cell_handle s, OutputIterator out) const +::compute_conflict_zone(const Point & p, Full_cell_handle s, OutputIterator out) const { CGAL_precondition( 2 <= current_dimension() ); if( current_dimension() < maximal_dimension() ) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 349d4b0f81c..e1996b39bca 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -247,13 +247,13 @@ public: } Vertex_handle insert(const Weighted_point &, - const Locate_type, + Locate_type, const Face &, const Facet &, - const Full_cell_handle); + Full_cell_handle); Vertex_handle insert(const Weighted_point & p, - const Full_cell_handle start = Full_cell_handle()) + Full_cell_handle start = Full_cell_handle()) { Locate_type lt; Face f(maximal_dimension()); @@ -262,7 +262,7 @@ public: return insert(p, lt, f, ft, s); } - Vertex_handle insert(const Weighted_point & p, const Vertex_handle hint) + Vertex_handle insert(const Weighted_point & p, Vertex_handle hint) { CGAL_assertion( Vertex_handle() != hint ); return insert(p, hint->full_cell()); @@ -270,19 +270,19 @@ public: Vertex_handle insert_outside_affine_hull(const Weighted_point &); Vertex_handle insert_in_conflicting_cell( - const Weighted_point &, const Full_cell_handle, - const Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle()); + const Weighted_point &, Full_cell_handle, + Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle()); Vertex_handle insert_if_in_star(const Weighted_point &, - const Vertex_handle, - const Locate_type, + Vertex_handle, + Locate_type, const Face &, const Facet &, - const Full_cell_handle); + Full_cell_handle); Vertex_handle insert_if_in_star( - const Weighted_point & p, const Vertex_handle star_center, - const Full_cell_handle start = Full_cell_handle()) + const Weighted_point & p, Vertex_handle star_center, + Full_cell_handle start = Full_cell_handle()) { Locate_type lt; Face f(maximal_dimension()); @@ -292,8 +292,8 @@ public: } Vertex_handle insert_if_in_star( - const Weighted_point & p, const Vertex_handle star_center, - const Vertex_handle hint) + const Weighted_point & p, Vertex_handle star_center, + Vertex_handle hint) { CGAL_assertion( Vertex_handle() != hint ); return insert_if_in_star(p, star_center, hint->full_cell()); @@ -308,7 +308,7 @@ public: Full_cell_const_handle, const OrientationPredicate &) const; template< typename OutputIterator > - Facet compute_conflict_zone(const Weighted_point &, const Full_cell_handle, OutputIterator) const; + Facet compute_conflict_zone(const Weighted_point &, Full_cell_handle, OutputIterator) const; template < typename OrientationPredicate, typename PowerTestPredicate > class Conflict_predicate @@ -801,7 +801,7 @@ Regular_triangulation template< typename Traits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation -::insert(const Weighted_point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) +::insert(const Weighted_point & p, Locate_type lt, const Face & f, const Facet & ft, Full_cell_handle s) { switch( lt ) { @@ -902,9 +902,11 @@ template< typename Traits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation ::insert_if_in_star(const Weighted_point & p, - const Vertex_handle star_center, - const Locate_type lt, const Face & f, const Facet & ft, - const Full_cell_handle s) + Vertex_handle star_center, + Locate_type lt, + const Face & f, + const Facet & ft, + Full_cell_handle s) { switch( lt ) { @@ -968,8 +970,8 @@ template< typename Traits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation ::insert_in_conflicting_cell(const Weighted_point & p, - const Full_cell_handle s, - const Vertex_handle only_if_this_vertex_is_in_the_cz) + Full_cell_handle s, + Vertex_handle only_if_this_vertex_is_in_the_cz) { typedef std::vector Full_cell_h_vector; @@ -1099,7 +1101,7 @@ template< typename Traits, typename TDS > template< typename OutputIterator > typename Regular_triangulation::Facet Regular_triangulation -::compute_conflict_zone(const Weighted_point & p, const Full_cell_handle s, OutputIterator out) const +::compute_conflict_zone(const Weighted_point & p, Full_cell_handle s, OutputIterator out) const { CGAL_precondition( 1 <= current_dimension() ); if( current_dimension() < maximal_dimension() ) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 06eaa4bfb04..d88a5608ede 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -258,7 +258,7 @@ public: // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS - Triangulation(int dim, const Geom_traits k = Geom_traits()) + Triangulation(int dim, const Geom_traits &k = Geom_traits()) : tds_(dim) , kernel_(k) , infinity_() @@ -529,7 +529,7 @@ public: bool is_infinite(const Facet & ft) const { Full_cell_const_handle s = full_cell(ft); - CGAL_precondition(s != Full_cell_handle()); + CGAL_precondition(s != Full_cell_const_handle()); if( is_infinite(s) ) return (s->vertex(index_of_covertex(ft)) != infinite_vertex()); return false; @@ -538,7 +538,7 @@ public: bool is_infinite(const Face & f) const { Full_cell_const_handle s = f.full_cell(); - CGAL_precondition(s != Full_cell_handle()); + CGAL_precondition(s != Full_cell_const_handle()); if( is_infinite(s) ) { Vertex_handle v; @@ -654,13 +654,13 @@ public: protected: template< typename OrientationPredicate > - Full_cell_handle do_locate( const Point &, Locate_type &, Face &, Facet &, - Full_cell_handle start, - const OrientationPredicate & o) const; + Full_cell_handle do_locate(const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle start, + const OrientationPredicate & o) const; public: - Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle locate(const Point &, Locate_type &, Face &, Facet &, Full_cell_handle start = Full_cell_handle()) const; - Full_cell_handle locate( const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle locate(const Point &, Locate_type &, Face &, Facet &, Vertex_handle) const; Full_cell_handle locate(const Point & p, Full_cell_handle s = Full_cell_handle()) const; Full_cell_handle locate(const Point & p, Vertex_handle v) const; @@ -685,7 +685,7 @@ public: } return number_of_vertices() - n; } - Vertex_handle insert(const Point &, const Locate_type, const Face &, const Facet &, const Full_cell_handle); + Vertex_handle insert(const Point &, Locate_type, const Face &, const Facet &, Full_cell_handle); Vertex_handle insert(const Point &, Full_cell_handle start = Full_cell_handle()); Vertex_handle insert(const Point &, Vertex_handle); template< typename ForwardIterator > @@ -823,7 +823,7 @@ Triangulation template < class TT, class TDS > typename Triangulation::Vertex_handle Triangulation -::insert(const Point & p, const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) +::insert(const Point & p, Locate_type lt, const Face & f, const Facet & ft, Full_cell_handle s) { switch( lt ) { @@ -1019,12 +1019,12 @@ template < class TT, class TDS > template< typename OrientationPredicate > typename Triangulation::Full_cell_handle Triangulation -::do_locate( const Point & p, // query point +::do_locate(const Point & p, // query point Locate_type & loc_type,// type of result (full_cell, face, vertex) Face & face,// the face containing the query in its interior (when appropriate) Facet & facet,// the facet containing the query in its interior (when appropriate) - const Full_cell_handle start// starting full_cell for the walk - , OrientationPredicate const& orientation_pred + Full_cell_handle start, // starting full_cell for the walk + OrientationPredicate const& orientation_pred ) const { const int cur_dim = current_dimension(); From e25f585eb54b7cac5ebc204702fb4e2edef95603 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 8 Sep 2016 15:53:05 +0200 Subject: [PATCH 467/487] Fix some parameters (const, ref...) doc --- .../CGAL/Delaunay_triangulation.h | 15 +++++++-------- .../CGAL/Regular_triangulation.h | 8 ++++---- .../doc/Triangulation/CGAL/Triangulation.h | 19 +++++++++---------- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h index ef86da814a1..59340449bf8 100644 --- a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h @@ -59,7 +59,7 @@ at infinity). See the description of the inherited nested type the use of the parameter `dim`. The complex stores a copy of the geometric traits `gt`. */ -Delaunay_triangulation(const int dim, const Geom_traits gt = Geom_traits()); +Delaunay_triangulation(int dim, const Geom_traits > = Geom_traits()); /// @} @@ -133,10 +133,10 @@ with `p`. The parameters `lt`, `f`, `ft` and `c` must be consistent with the localization of point `p` in the Delaunay triangulation e.g. by a call to -`Triangulation::locate(const Point &, Locate_type &, Face &, Vertex_handle) const`. +`Triangulation::locate(const Point &, Locate_type, Face &, Vertex_handle) const`. */ -Vertex_handle insert(const Point & p, const Locate_type lt, -const Face & f, const Facet & ft, const Full_cell_handle c); +Vertex_handle insert(const Point & p, Locate_type lt, +const Face & f, const Facet & ft, Full_cell_handle c); /// @} @@ -148,8 +148,7 @@ Returns `true` if and only if the point `p` is in (Delaunay) conflict with full cell `c` (i.e., the circumscribing ball of \f$ c\f$ contains \f$ p\f$ in its interior). */ -bool is_in_conflict(const Point & p, Full_cell_const_handle c) -const; +bool is_in_conflict(const Point & p, Full_cell_const_handle c) const; /*! Outputs handles to the full cells in conflict with @@ -161,8 +160,8 @@ A facet `(cc,i)` on the boundary of the conflict zone with \pre `c` is in conflict with `p` and `dt`.`current_dimension()`\f$ \geq2\f$. */ template< typename OutputIterator > -Facet compute_conflict_zone(const Point & p, const Full_cell_handle c, -OutputIterator out) const; +Facet compute_conflict_zone(const Point & p, Full_cell_handle c, + OutputIterator out) const; /// @} diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index bf1b463770d..0e885c5a659 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -64,7 +64,7 @@ at infinity). See the description of the inherited nested type the use of the parameter `dim`. The triangulation stores a copy of the geometric traits `gt`. */ -Regular_triangulation(const int dim, const Geom_traits gt = Geom_traits()); +Regular_triangulation(int dim, const Geom_traits > = Geom_traits()); /// @} @@ -106,8 +106,8 @@ Similar to the above `insert()` function, but takes as additional parameter the return values of a previous location query. See description of `Triangulation::locate()`. */ -Vertex_handle insert(const Weighted_point & p, const Locate_type lt, - const Face & f, const Facet & ft, const Full_cell_handle c); +Vertex_handle insert(const Weighted_point & p, Locate_type lt, + const Face & f, const Facet & ft, Full_cell_handle c); /*! Inserts the weighted points found in range `[s,e)` in the regular triangulation. @@ -146,7 +146,7 @@ A facet `(cc,i)` on the boundary of the conflict zone with \pre `c` is in conflict with `p` and `rt`.`current_dimension()`\f$ \geq 1\f$. */ template< typename OutputIterator > -Facet compute_conflict_zone(const Weighted_point & p, const Full_cell_handle c, +Facet compute_conflict_zone(const Weighted_point & p, Full_cell_handle c, OutputIterator out) const; /// @} diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index b43accc0214..33df14d0200 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -235,8 +235,7 @@ description of the nested type `Maximal_dimension` above for an explanation of the use of the parameter `dim`. The triangulation stores a copy of the geometric traits `gt`. */ -Triangulation(const int dim, const Geom_traits & gt = -Geom_traits()); +Triangulation(int dim, const Geom_traits & gt = Geom_traits()); /*! The copy constructor. @@ -323,13 +322,13 @@ size_type number_of_finite_full_cells() const; /*! Returns `true` if and only if the vertex `v` is the infinite vertex. */ -bool is_infinite(const Vertex_handle v) const; +bool is_infinite(Vertex_handle v) const; /*! Returns `true` if and only if `c` is incident to the infinite vertex. */ -bool is_infinite(const Full_cell_handle c) const; +bool is_infinite(Full_cell_handle c) const; /*! Returns `true` if and only if facet `ft` is incident to the infinite @@ -455,7 +454,7 @@ p_1, p_2, \ldots, p_d, \infty\}\f$ is returned such that the full cell \f$ (p_1, on the other side of facet \f$ (p_1, p_2, \ldots, p_d)\f$). */ Full_cell_handle locate(const Point & query, -Full_cell_handle hint = Full_cell_handle()) const; + Full_cell_handle hint = Full_cell_handle()) const; /*! Same as above but `hint` is a vertex and not a full cell. @@ -496,7 +495,7 @@ as in the `locate` method above. If the `query` point lies `loc_type` is set to `IN_FULL_CELL` and the unique full cell containing the `query` point is returned. */ -Full_cell_handle locate(const Point & query, Locate_type & loc_type, +Full_cell_handle locate(const Point & query, Locate_type loc_type, Face & f, Facet & ft, Full_cell_handle hint = Full_cell_handle()) const; /*! @@ -505,7 +504,7 @@ The parameter `hint` is ignored if it is a default constructed `Vertex_handle()`. */ Full_cell_handle -locate(const Point & query, Locate_type & loc_type, +locate(const Point & query, Locate_type loc_type, Face & f, Vertex_handle hint) const; /// @} @@ -543,13 +542,13 @@ Inserts point `p` in the triangulation. Returns a Prior to the actual insertion, `p` is located in the triangulation; `hint` is used as a starting place for locating `p`. */ -Vertex_handle insert(const Point p, Full_cell_handle hint = +Vertex_handle insert(const Point &p, Full_cell_handle hint = Full_cell_handle()); /*! Same as above but uses a vertex `hint` as the starting place for the search. */ -Vertex_handle insert(const Point p, Vertex_handle hint); +Vertex_handle insert(const Point &p, Vertex_handle hint); /*! Inserts point `p` into the triangulation and returns a handle to the @@ -566,7 +565,7 @@ of `loc_type`, using the full cell `c`. This method is used internally by the other `insert()` methods. */ -Vertex_handle insert(const Point p, Locate_type loc_type, Face & f, Facet & ft, Full_cell_handle c); +Vertex_handle insert(const Point &p, Locate_type loc_type, Face & f, Facet & ft, Full_cell_handle c); /*! Removes the full cells in the range \f$ C=\f$`[s, e)`, inserts a vertex From d3c838e4cd9c1783cc948272b9d10ca1d514b7bf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 8 Sep 2016 16:15:38 +0200 Subject: [PATCH 468/487] Remove more const & other minor fixes --- .../doc/Triangulation/CGAL/Triangulation.h | 2 +- Triangulation/include/CGAL/Triangulation.h | 34 +++++----- .../CGAL/Triangulation_data_structure.h | 68 +++++++++---------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index 33df14d0200..9cdd73e167c 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -454,7 +454,7 @@ p_1, p_2, \ldots, p_d, \infty\}\f$ is returned such that the full cell \f$ (p_1, on the other side of facet \f$ (p_1, p_2, \ldots, p_d)\f$). */ Full_cell_handle locate(const Point & query, - Full_cell_handle hint = Full_cell_handle()) const; + Full_cell_const_handle hint = Full_cell_handle()) const; /*! Same as above but `hint` is a vertex and not a full cell. diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index d88a5608ede..49170a62380 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -139,20 +139,20 @@ public: typedef Maximal_dimension_ Maximal_dimension; typedef typename Geom_traits::Point_d Point; - typedef typename TDS::Vertex_handle Vertex_handle; - typedef typename TDS::Vertex_iterator Vertex_iterator; - typedef typename TDS::Vertex_const_handle Vertex_const_handle; - typedef typename TDS::Vertex_const_iterator Vertex_const_iterator; + typedef typename TDS::Vertex_handle Vertex_handle; + typedef typename TDS::Vertex_iterator Vertex_iterator; + typedef typename TDS::Vertex_const_handle Vertex_const_handle; + typedef typename TDS::Vertex_const_iterator Vertex_const_iterator; - typedef typename TDS::Full_cell_handle Full_cell_handle; - typedef typename TDS::Full_cell_iterator Full_cell_iterator; - typedef typename TDS::Full_cell_const_handle Full_cell_const_handle; - typedef typename TDS::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename TDS::Full_cell_handle Full_cell_handle; + typedef typename TDS::Full_cell_iterator Full_cell_iterator; + typedef typename TDS::Full_cell_const_handle Full_cell_const_handle; + typedef typename TDS::Full_cell_const_iterator Full_cell_const_iterator; - typedef typename TDS::Facet_iterator Facet_iterator; + typedef typename TDS::Facet_iterator Facet_iterator; - typedef typename TDS::size_type size_type; - typedef typename TDS::difference_type difference_type; + typedef typename TDS::size_type size_type; + typedef typename TDS::difference_type difference_type; /// The type of location a new point is found lying on enum Locate_type @@ -182,18 +182,18 @@ public: protected: // DATA MEMBERS - Triangulation_ds tds_; - const Geom_traits kernel_; - Vertex_handle infinity_; - mutable std::vector orientations_; + Triangulation_ds tds_; + const Geom_traits kernel_; + Vertex_handle infinity_; + mutable std::vector orientations_; mutable boost::optional flat_orientation_; // The user can specify a Flat_orientation_d object to be used for // orienting simplices of a specific dimension // (= preset_flat_orientation_.first) // preset_flat_orientation_.first = numeric_limits::max() otherwise) - std::pair preset_flat_orientation_; + std::pair preset_flat_orientation_; // for stochastic walk in the locate() function: - mutable Random rng_; + mutable Random rng_; #ifdef CGAL_TRIANGULATION_STATISTICS mutable unsigned long walk_size_; #endif diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 915f93b9775..fe175e43a29 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -154,13 +154,13 @@ private: template < class Dim_tag > struct get_maximal_dimension { - static int value(const int D) { return D; } + static int value(int D) { return D; } }; // specialization template < int D > struct get_maximal_dimension > { - static int value(const int) { return D; } + static int value(int) { return D; } }; public: @@ -208,7 +208,7 @@ public: protected: - bool check_range(const int i) const + bool check_range(int i) const { if( current_dimension() < 0 ) { @@ -242,19 +242,19 @@ public: Full_cell_container & full_cells() { return full_cells_; } const Full_cell_container & full_cells() const { return full_cells_; } - Vertex_handle vertex(const Full_cell_handle s, const int i) const /* Concept */ + Vertex_handle vertex(Full_cell_handle s, int i) const /* Concept */ { CGAL_precondition(s != Full_cell_handle() && check_range(i)); return s->vertex(i); } - Vertex_const_handle vertex(const Full_cell_const_handle s, const int i) const /* Concept */ + Vertex_const_handle vertex(Full_cell_const_handle s, int i) const /* Concept */ { CGAL_precondition(s != Full_cell_handle() && check_range(i)); return s->vertex(i); } - bool is_vertex(const Vertex_const_handle & v) const /* Concept */ + bool is_vertex(Vertex_const_handle v) const /* Concept */ { if( Vertex_const_handle() == v ) return false; @@ -264,7 +264,7 @@ public: return v == vit; } - bool is_full_cell(const Full_cell_const_handle & s) const /* Concept */ + bool is_full_cell(Full_cell_const_handle s) const /* Concept */ { if( Full_cell_const_handle() == s ) return false; @@ -274,43 +274,43 @@ public: return s == sit; } - Full_cell_handle full_cell(const Vertex_handle v) const /* Concept */ + Full_cell_handle full_cell(Vertex_handle v) const /* Concept */ { CGAL_precondition(v != Vertex_handle()); return v->full_cell(); } - Full_cell_const_handle full_cell(const Vertex_const_handle v) const /* Concept */ + Full_cell_const_handle full_cell(Vertex_const_handle v) const /* Concept */ { CGAL_precondition(Vertex_const_handle() != v); return v->full_cell(); } - Full_cell_handle neighbor(const Full_cell_handle s, const int i) const /* Concept */ + Full_cell_handle neighbor(Full_cell_handle s, int i) const /* Concept */ { CGAL_precondition(Full_cell_handle() != s && check_range(i)); return s->neighbor(i); } - Full_cell_const_handle neighbor(const Full_cell_const_handle s, const int i) const/* Concept */ + Full_cell_const_handle neighbor(Full_cell_const_handle s, int i) const/* Concept */ { CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); return s->neighbor(i); } - int mirror_index(const Full_cell_handle s, const int i) const /* Concept */ + int mirror_index(Full_cell_handle s, int i) const /* Concept */ { CGAL_precondition(Full_cell_handle() != s && check_range(i)); return s->mirror_index(i); } - int mirror_index(const Full_cell_const_handle s, const int i) const + int mirror_index(Full_cell_const_handle s, int i) const { CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); /* Concept */ return s->mirror_index(i); } - int mirror_vertex(const Full_cell_handle s, const int i) const /* Concept */ + int mirror_vertex(Full_cell_handle s, int i) const /* Concept */ { CGAL_precondition(Full_cell_handle() != s && check_range(i)); return s->mirror_vertex(i); @@ -365,7 +365,7 @@ public: // NICE UPDATE OPERATIONS protected: - void do_insert_increase_dimension(const Vertex_handle, const Vertex_handle); + void do_insert_increase_dimension(Vertex_handle, Vertex_handle); public: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS @@ -378,9 +378,9 @@ public: Vertex_handle insert_in_face(const Face &); /* Concept */ Vertex_handle insert_in_facet(const Facet &); /* Concept */ template< typename Forward_iterator > - Vertex_handle insert_in_hole(Forward_iterator, const Forward_iterator, Facet); /* Concept */ + Vertex_handle insert_in_hole(Forward_iterator, Forward_iterator, Facet); /* Concept */ template< typename Forward_iterator, typename OutputIterator > - Vertex_handle insert_in_hole(Forward_iterator, const Forward_iterator, Facet, OutputIterator); /* Concept */ + Vertex_handle insert_in_hole(Forward_iterator, Forward_iterator, Facet, OutputIterator); /* Concept */ template< typename OutputIterator > Full_cell_handle insert_in_tagged_hole(Vertex_handle, Facet, OutputIterator); @@ -445,13 +445,13 @@ public: dcur_ = -2; } - void set_current_dimension(const int d) /* Concept */ + void set_current_dimension(int d) /* Concept */ { CGAL_precondition(-2<=d && d<=maximal_dimension()); dcur_ = d; } - Full_cell_handle new_full_cell(const Full_cell_handle s) + Full_cell_handle new_full_cell(Full_cell_handle s) { return full_cells_.emplace(*s); } @@ -493,7 +493,7 @@ public: vertices_.erase(v); } - void associate_vertex_with_full_cell(Full_cell_handle s, const int i, Vertex_handle v) /* Concept */ + void associate_vertex_with_full_cell(Full_cell_handle s, int i, Vertex_handle v) /* Concept */ { CGAL_precondition(check_range(i)); CGAL_precondition(s != Full_cell_handle()); @@ -553,7 +553,7 @@ public: const Triangulation_data_structure & tds_; public: Incident_full_cell_traversal_predicate(const Triangulation_data_structure & tds, - const Face & f) + const Face & f) : f_(f), tds_(tds) { dim_ = f.face_dimension(); @@ -578,7 +578,7 @@ public: const Triangulation_data_structure & tds_; public: Star_traversal_predicate(const Triangulation_data_structure & tds, - const Face & f) + const Face & f) : f_(f), tds_(tds) { dim_ = f.face_dimension(); @@ -606,27 +606,27 @@ public: OutputIterator star(const Face &, OutputIterator) const; /* Concept */ #ifndef CGAL_CFG_NO_CPP0X_DEFAULT_TEMPLATE_ARGUMENTS_FOR_FUNCTION_TEMPLATES template< typename OutputIterator, typename Comparator = std::less > - OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator()) + OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp = Comparator()) { return incident_faces(v, dim, out, cmp, true); } template< typename OutputIterator, typename Comparator = std::less > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false) const; + OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator, Comparator = Comparator(), bool = false) const; #else template< typename OutputIterator, typename Comparator > - OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator()) + OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp = Comparator()) { return incident_faces(v, dim, out, cmp, true); } template< typename OutputIterator > - OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out) + OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out) { return incident_faces(v, dim, out, std::less(), true); } template< typename OutputIterator, typename Comparator > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false) const; + OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator, Comparator = Comparator(), bool = false) const; template< typename OutputIterator > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, + OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator, std::less = std::less(), bool = false) const; #endif @@ -722,7 +722,7 @@ template< class Dim, class Vb, class Fcb > template< typename OutputIterator > OutputIterator Triangulation_data_structure -::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, +::incident_faces(Vertex_const_handle v, int dim, OutputIterator out, std::less cmp, bool upper_faces) const { return incident_faces >(v, dim, out, cmp, upper_faces); @@ -733,7 +733,7 @@ template< class Dim, class Vb, class Fcb > template< typename OutputIterator, typename Comparator > OutputIterator Triangulation_data_structure -::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp, bool upper_faces) const +::incident_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp, bool upper_faces) const { CGAL_precondition( 0 < dim ); if( dim >= current_dimension() ) @@ -966,10 +966,10 @@ Triangulation_data_structure CGAL_assertion_msg(is_boundary_facet(f), "starting facet should be on the hole boundary"); const int cur_dim = current_dimension(); - Full_cell_handle new_s; + Full_cell_handle new_s; - std::queue task_queue; - task_queue.push( + std::queue task_queue; + task_queue.push( IITH_task(f, mirror_index(full_cell(f), index_of_covertex(f))) ); while (!task_queue.empty()) @@ -1115,7 +1115,7 @@ Triangulation_data_structure template void Triangulation_data_structure -::do_insert_increase_dimension(const Vertex_handle x, const Vertex_handle star) +::do_insert_increase_dimension(Vertex_handle x, Vertex_handle star) { Full_cell_handle start = full_cells_begin(); Full_cell_handle swap_me; From bbb8f5978349231b51dffeaac7c638d31bad706c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 8 Sep 2016 16:21:14 +0200 Subject: [PATCH 469/487] Restore some references --- .../doc/Triangulation/CGAL/Delaunay_triangulation.h | 2 +- Triangulation/doc/Triangulation/CGAL/Triangulation.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h index 59340449bf8..fe74b7336f9 100644 --- a/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Delaunay_triangulation.h @@ -133,7 +133,7 @@ with `p`. The parameters `lt`, `f`, `ft` and `c` must be consistent with the localization of point `p` in the Delaunay triangulation e.g. by a call to -`Triangulation::locate(const Point &, Locate_type, Face &, Vertex_handle) const`. +`Triangulation::locate(const Point &, Locate_type &, Face &, Vertex_handle) const`. */ Vertex_handle insert(const Point & p, Locate_type lt, const Face & f, const Facet & ft, Full_cell_handle c); diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index 9cdd73e167c..9f198797dd9 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -495,7 +495,7 @@ as in the `locate` method above. If the `query` point lies `loc_type` is set to `IN_FULL_CELL` and the unique full cell containing the `query` point is returned. */ -Full_cell_handle locate(const Point & query, Locate_type loc_type, +Full_cell_handle locate(const Point & query, Locate_type & loc_type, Face & f, Facet & ft, Full_cell_handle hint = Full_cell_handle()) const; /*! @@ -504,8 +504,8 @@ The parameter `hint` is ignored if it is a default constructed `Vertex_handle()`. */ Full_cell_handle -locate(const Point & query, Locate_type loc_type, -Face & f, Vertex_handle hint) const; +locate(const Point & query, Locate_type & loc_type, + Face & f, Vertex_handle hint) const; /// @} From e79d8f461e030ba88f8a25684ebe5e5874da2db9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 8 Sep 2016 17:08:56 +0200 Subject: [PATCH 470/487] Don't write std::endl in binary mode --- Triangulation/include/CGAL/Triangulation_data_structure.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index fe175e43a29..01fe409dde6 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -1591,7 +1591,9 @@ operator<<(std::ostream & os, const Triangulation_data_structure int i = 0; for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it, ++i ) { - os << *it << std::endl; // write the vertex + os << *it; // write the vertex + if (is_ascii(os)) + os << std::endl; index_of_vertex[it] = i; } CGAL_assertion( (std::size_t) i == n ); From 64a34853eafce8360e9ee3a76c7964402cab7a32 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 20 Sep 2016 16:18:08 +0200 Subject: [PATCH 471/487] Point_drop_weight_d -> Compute_weight_d --- .../CGAL/NewKernel_d/Kernel_d_interface.h | 4 ++-- NewKernel_d/test/NewKernel_d/Epick_d.cpp | 8 ++++---- .../Concepts/RegularTriangulationTraits.h | 4 ++-- .../CGAL/IO/Triangulation_off_ostream.h | 4 ++-- .../Regular_triangulation_traits_adapter.h | 18 +++++++++--------- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index f7f89413b7a..30cbd8c0cea 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -173,7 +173,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Construct_max_vertex_d; typedef typename Get_functor::type Point_weight_d; - typedef typename Get_functor::type Point_drop_weight_d; + typedef typename Get_functor::type Compute_weight_d; //TODO: //typedef ??? Intersect_d; @@ -240,7 +240,7 @@ template struct Kernel_d_interface : public Base_ { Construct_weighted_point_d construct_weighted_point_d_object()const{ return Construct_weighted_point_d(*this); } Point_weight_d point_weight_d_object()const{ return Point_weight_d(*this); } - Point_drop_weight_d point_drop_weight_d_object()const{ return Point_drop_weight_d(*this); } + Compute_weight_d compute_weight_d_object()const{ return Compute_weight_d(*this); } // Dummies for those required functors missing a concept. typedef Null_functor Position_on_line_d; diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index a6c73673be0..1c543a27607 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -143,7 +143,7 @@ void test2(){ typedef typename K1::Power_distance_d PoD; typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; - typedef typename K1::Point_drop_weight_d PDW; + typedef typename K1::Compute_weight_d PDW; typedef typename K1::Point_weight_d PW; CGAL_USE_TYPE(AT); @@ -209,7 +209,7 @@ void test2(){ TP tp Kinit(translated_point_d_object); PC pc Kinit(power_center_d_object); CWP cwp Kinit(construct_weighted_point_d_object); - PDW pdw Kinit(point_drop_weight_d_object); + PDW pdw Kinit(compute_weight_d_object); PW pw Kinit(point_weight_d_object); PoD pod Kinit(power_distance_d_object); @@ -629,12 +629,12 @@ void test3(){ typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; - typedef typename K1::Point_drop_weight_d PDW; + typedef typename K1::Compute_weight_d PDW; typedef typename K1::Point_weight_d PW; typedef typename K1::Power_side_of_power_sphere_d PT; typedef typename K1::In_flat_power_side_of_power_sphere_d IFPT; CWP cwp Kinit(construct_weighted_point_d_object); - PDW pdw Kinit(point_drop_weight_d_object); + PDW pdw Kinit(compute_weight_d_object); PW pw Kinit(point_weight_d_object); PT pt Kinit(power_side_of_power_sphere_d_object); IFPT ifpt Kinit(in_flat_power_side_of_power_sphere_d_object); diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index d313caa5f03..5c929c11967 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -39,7 +39,7 @@ A function object that must provide the operator `Point_d operator()(const Weighted_point_d & wp)`, returning `wp` without its weight. */ -typedef unspecified_type Point_drop_weight_d; +typedef unspecified_type Compute_weight_d; /*! A function object that must provide the operator @@ -115,7 +115,7 @@ RegularTriangulationTraits(); /*! */ -Point_drop_weight_d point_drop_weight_d_object() const; +Compute_weight_d compute_weight_d_object() const; /*! diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 892819ab3b2..90480230910 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -54,8 +54,8 @@ output_weighted_point(std::ostream & os, const Traits &traits, const P & p, bool output_weight = true) { typedef typename Traits::Compute_coordinate_d Ccd; - typename Traits::Point_drop_weight_d drop_w = - traits.point_drop_weight_d_object(); + typename Traits::Compute_weight_d drop_w = + traits.compute_weight_d_object(); typename Traits::Point_weight_d pt_weight = traits.point_weight_d_object(); const Ccd ccd = traits.compute_coordinate_d_object(); const int dim = traits.point_dimension_d_object()(p); diff --git a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h index f88a32ba417..8d1cd146257 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h +++ b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h @@ -50,7 +50,7 @@ public: // Required by RegularTriangulationTraits typedef typename K::Point_d Bare_point_d; typedef typename K::Weighted_point_d Weighted_point_d; - typedef typename K::Point_drop_weight_d Point_drop_weight_d; + typedef typename K::Compute_weight_d Compute_weight_d; typedef typename K::Point_weight_d Point_weight_d; typedef typename K::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; typedef typename K::In_flat_power_side_of_power_sphere_d @@ -74,7 +74,7 @@ public: result_type operator()( Weighted_point_d const& p, Weighted_point_d const& q, int i) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Compute_weight_d pdw = m_kernel.compute_weight_d_object(); return m_kernel.less_coordinate_d_object() (pdw(p), pdw(q), i); } }; @@ -95,7 +95,7 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Compute_weight_d pdw = m_kernel.compute_weight_d_object(); return m_kernel.orientation_d_object() ( boost::make_transform_iterator(start, pdw), boost::make_transform_iterator(end, pdw) @@ -119,7 +119,7 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Compute_weight_d pdw = m_kernel.compute_weight_d_object(); return m_kernel.construct_flat_orientation_d_object() ( boost::make_transform_iterator(start, pdw), boost::make_transform_iterator(end, pdw) @@ -145,7 +145,7 @@ public: result_type operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Compute_weight_d pdw = m_kernel.compute_weight_d_object(); return m_kernel.in_flat_orientation_d_object() ( orient, boost::make_transform_iterator(start, pdw), @@ -171,7 +171,7 @@ public: result_type operator()(ForwardIterator start, ForwardIterator end, const Weighted_point_d & p) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Compute_weight_d pdw = m_kernel.compute_weight_d_object(); return m_kernel.contained_in_affine_hull_d_object() ( boost::make_transform_iterator(start, pdw), boost::make_transform_iterator(end, pdw), @@ -196,7 +196,7 @@ public: result_type operator()( const Weighted_point_d & p, const Weighted_point_d & q) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Compute_weight_d pdw = m_kernel.compute_weight_d_object(); return m_kernel.compare_lexicographically_d_object()(pdw(p), pdw(q)); } }; @@ -217,7 +217,7 @@ public: result_type operator()( const Weighted_point_d & p, const int i) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Compute_weight_d pdw = m_kernel.compute_weight_d_object(); return m_kernel.compute_coordinate_d_object()(pdw(p), i); } }; @@ -239,7 +239,7 @@ public: result_type operator()( const Weighted_point_d & p) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Compute_weight_d pdw = m_kernel.compute_weight_d_object(); return m_kernel.point_dimension_d_object()(pdw(p)); } }; From 1d540b1dd95e8dd721a4120fedd030c82476ad75 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 20 Sep 2016 17:21:55 +0200 Subject: [PATCH 472/487] Revert "Point_drop_weight_d -> Compute_weight_d" This reverts commit 64a34853eafce8360e9ee3a76c7964402cab7a32. --- .../CGAL/NewKernel_d/Kernel_d_interface.h | 4 ++-- NewKernel_d/test/NewKernel_d/Epick_d.cpp | 8 ++++---- .../Concepts/RegularTriangulationTraits.h | 4 ++-- .../CGAL/IO/Triangulation_off_ostream.h | 4 ++-- .../Regular_triangulation_traits_adapter.h | 18 +++++++++--------- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index 30cbd8c0cea..f7f89413b7a 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -173,7 +173,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Construct_max_vertex_d; typedef typename Get_functor::type Point_weight_d; - typedef typename Get_functor::type Compute_weight_d; + typedef typename Get_functor::type Point_drop_weight_d; //TODO: //typedef ??? Intersect_d; @@ -240,7 +240,7 @@ template struct Kernel_d_interface : public Base_ { Construct_weighted_point_d construct_weighted_point_d_object()const{ return Construct_weighted_point_d(*this); } Point_weight_d point_weight_d_object()const{ return Point_weight_d(*this); } - Compute_weight_d compute_weight_d_object()const{ return Compute_weight_d(*this); } + Point_drop_weight_d point_drop_weight_d_object()const{ return Point_drop_weight_d(*this); } // Dummies for those required functors missing a concept. typedef Null_functor Position_on_line_d; diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 1c543a27607..a6c73673be0 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -143,7 +143,7 @@ void test2(){ typedef typename K1::Power_distance_d PoD; typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; - typedef typename K1::Compute_weight_d PDW; + typedef typename K1::Point_drop_weight_d PDW; typedef typename K1::Point_weight_d PW; CGAL_USE_TYPE(AT); @@ -209,7 +209,7 @@ void test2(){ TP tp Kinit(translated_point_d_object); PC pc Kinit(power_center_d_object); CWP cwp Kinit(construct_weighted_point_d_object); - PDW pdw Kinit(compute_weight_d_object); + PDW pdw Kinit(point_drop_weight_d_object); PW pw Kinit(point_weight_d_object); PoD pod Kinit(power_distance_d_object); @@ -629,12 +629,12 @@ void test3(){ typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; - typedef typename K1::Compute_weight_d PDW; + typedef typename K1::Point_drop_weight_d PDW; typedef typename K1::Point_weight_d PW; typedef typename K1::Power_side_of_power_sphere_d PT; typedef typename K1::In_flat_power_side_of_power_sphere_d IFPT; CWP cwp Kinit(construct_weighted_point_d_object); - PDW pdw Kinit(compute_weight_d_object); + PDW pdw Kinit(point_drop_weight_d_object); PW pw Kinit(point_weight_d_object); PT pt Kinit(power_side_of_power_sphere_d_object); IFPT ifpt Kinit(in_flat_power_side_of_power_sphere_d_object); diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 5c929c11967..d313caa5f03 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -39,7 +39,7 @@ A function object that must provide the operator `Point_d operator()(const Weighted_point_d & wp)`, returning `wp` without its weight. */ -typedef unspecified_type Compute_weight_d; +typedef unspecified_type Point_drop_weight_d; /*! A function object that must provide the operator @@ -115,7 +115,7 @@ RegularTriangulationTraits(); /*! */ -Compute_weight_d compute_weight_d_object() const; +Point_drop_weight_d point_drop_weight_d_object() const; /*! diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 90480230910..892819ab3b2 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -54,8 +54,8 @@ output_weighted_point(std::ostream & os, const Traits &traits, const P & p, bool output_weight = true) { typedef typename Traits::Compute_coordinate_d Ccd; - typename Traits::Compute_weight_d drop_w = - traits.compute_weight_d_object(); + typename Traits::Point_drop_weight_d drop_w = + traits.point_drop_weight_d_object(); typename Traits::Point_weight_d pt_weight = traits.point_weight_d_object(); const Ccd ccd = traits.compute_coordinate_d_object(); const int dim = traits.point_dimension_d_object()(p); diff --git a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h index 8d1cd146257..f88a32ba417 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h +++ b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h @@ -50,7 +50,7 @@ public: // Required by RegularTriangulationTraits typedef typename K::Point_d Bare_point_d; typedef typename K::Weighted_point_d Weighted_point_d; - typedef typename K::Compute_weight_d Compute_weight_d; + typedef typename K::Point_drop_weight_d Point_drop_weight_d; typedef typename K::Point_weight_d Point_weight_d; typedef typename K::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; typedef typename K::In_flat_power_side_of_power_sphere_d @@ -74,7 +74,7 @@ public: result_type operator()( Weighted_point_d const& p, Weighted_point_d const& q, int i) const { - Compute_weight_d pdw = m_kernel.compute_weight_d_object(); + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.less_coordinate_d_object() (pdw(p), pdw(q), i); } }; @@ -95,7 +95,7 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - Compute_weight_d pdw = m_kernel.compute_weight_d_object(); + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.orientation_d_object() ( boost::make_transform_iterator(start, pdw), boost::make_transform_iterator(end, pdw) @@ -119,7 +119,7 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - Compute_weight_d pdw = m_kernel.compute_weight_d_object(); + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.construct_flat_orientation_d_object() ( boost::make_transform_iterator(start, pdw), boost::make_transform_iterator(end, pdw) @@ -145,7 +145,7 @@ public: result_type operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end) const { - Compute_weight_d pdw = m_kernel.compute_weight_d_object(); + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.in_flat_orientation_d_object() ( orient, boost::make_transform_iterator(start, pdw), @@ -171,7 +171,7 @@ public: result_type operator()(ForwardIterator start, ForwardIterator end, const Weighted_point_d & p) const { - Compute_weight_d pdw = m_kernel.compute_weight_d_object(); + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.contained_in_affine_hull_d_object() ( boost::make_transform_iterator(start, pdw), boost::make_transform_iterator(end, pdw), @@ -196,7 +196,7 @@ public: result_type operator()( const Weighted_point_d & p, const Weighted_point_d & q) const { - Compute_weight_d pdw = m_kernel.compute_weight_d_object(); + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.compare_lexicographically_d_object()(pdw(p), pdw(q)); } }; @@ -217,7 +217,7 @@ public: result_type operator()( const Weighted_point_d & p, const int i) const { - Compute_weight_d pdw = m_kernel.compute_weight_d_object(); + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.compute_coordinate_d_object()(pdw(p), i); } }; @@ -239,7 +239,7 @@ public: result_type operator()( const Weighted_point_d & p) const { - Compute_weight_d pdw = m_kernel.compute_weight_d_object(); + Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); return m_kernel.point_dimension_d_object()(pdw(p)); } }; From 49fda9d7e6112dd9db452ba3ea3ce5760948ad06 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 21 Sep 2016 15:33:37 +0200 Subject: [PATCH 473/487] This file should never have been commited --- Triangulation/include/CGAL/Convex_hull.h | 56 ------------------------ 1 file changed, 56 deletions(-) delete mode 100644 Triangulation/include/CGAL/Convex_hull.h diff --git a/Triangulation/include/CGAL/Convex_hull.h b/Triangulation/include/CGAL/Convex_hull.h deleted file mode 100644 index a8f91bf8d32..00000000000 --- a/Triangulation/include/CGAL/Convex_hull.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL$ -// $Id$ -// -// Author(s) : Samuel Hornus - -/* RANDOM DESIGN IDEAS: -- Use a policy tag to choose for incremental with inserts only or - incremental with removals and inserts. - In the first case: use Triangulation for storage. - In the second case: use Delaunay ! - In this second case, we must keeps the points that are inserted in the hull, - as they may become part of the boundary later on, when some points are removed. -- Constructor with range argument uses quickhull. -*/ - -#ifndef CGAL_CONVEX_HULL_H -#define CGAL_CONVEX_HULL_H - -namespace CGAL { - -template < class CHTraits, class TDS_ = Default > -class Convex_hull -{ - typedef typename Maximal_dimension::type - Maximal_dimension_; - typedef typename Default::Get, - Triangulation_full_cell > - >::type TDS; - typedef Convex_hull Self; - - typedef typename CHTraits::Coaffine_orientation_d - Coaffine_orientation_d; - typedef typename CHTraits::Orientation_d Orientation_d; - -public: -}; - -} //namespace CGAL - -#endif // CGAL_CONVEX_HULL_H From 58279a0812c8e51439f338e73832193c3ff0e265 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 21 Sep 2016 15:52:41 +0200 Subject: [PATCH 474/487] These lines were commited by mistake --- .../benchmark/Triangulation_3/Triangulation_benchmark_3.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Triangulation_3/benchmark/Triangulation_3/Triangulation_benchmark_3.cpp b/Triangulation_3/benchmark/Triangulation_3/Triangulation_benchmark_3.cpp index f0db573b038..a7c0d66c373 100644 --- a/Triangulation_3/benchmark/Triangulation_3/Triangulation_benchmark_3.cpp +++ b/Triangulation_3/benchmark/Triangulation_3/Triangulation_benchmark_3.cpp @@ -303,9 +303,6 @@ void benchmark_remove() Time_accumulator tt(time); tr.remove(&vhs[0], &vhs[NUM_VERTICES_TO_REMOVE - 1]); ++iterations; - //std::cout<<"\b\b\b\b\b\b"< Date: Wed, 21 Sep 2016 19:28:33 +0200 Subject: [PATCH 475/487] Unused local typedefs. --- Triangulation/include/CGAL/Triangulation_data_structure.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 01fe409dde6..2493c7125da 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -1516,8 +1516,6 @@ operator>>(std::istream & is, Triangulation_data_structure & tr) // - the neighbors of each full_cell by their index in the preceding list { typedef Triangulation_data_structure TDS; - typedef typename TDS::Full_cell_handle Full_cell_handle; - typedef typename TDS::Full_cell_iterator Full_cell_iterator; typedef typename TDS::Vertex_handle Vertex_handle; // read current dimension and number of vertices @@ -1568,8 +1566,6 @@ operator<<(std::ostream & os, const Triangulation_data_structure // - the neighbors of each full_cell by their index in the preceding list { typedef Triangulation_data_structure TDS; - typedef typename TDS::Full_cell_const_handle Full_cell_handle; - typedef typename TDS::Full_cell_const_iterator Full_cell_iterator; typedef typename TDS::Vertex_const_handle Vertex_handle; typedef typename TDS::Vertex_const_iterator Vertex_iterator; From 8aa0ede187a3eca487343e8baf8fb8fec5134cd8 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 21 Sep 2016 19:38:42 +0200 Subject: [PATCH 476/487] Point_weight_d -> Compute_weight_d --- NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h | 4 ++-- NewKernel_d/test/NewKernel_d/Epick_d.cpp | 8 ++++---- .../Triangulation/Concepts/RegularTriangulationTraits.h | 4 ++-- Triangulation/include/CGAL/IO/Triangulation_off_ostream.h | 2 +- Triangulation/include/CGAL/Regular_triangulation.h | 8 ++++---- .../include/CGAL/Regular_triangulation_traits_adapter.h | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index f7f89413b7a..6983f641841 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -172,7 +172,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Construct_min_vertex_d; typedef typename Get_functor::type Construct_max_vertex_d; - typedef typename Get_functor::type Point_weight_d; + typedef typename Get_functor::type Compute_weight_d; typedef typename Get_functor::type Point_drop_weight_d; //TODO: @@ -239,7 +239,7 @@ template struct Kernel_d_interface : public Base_ { Construct_max_vertex_d construct_max_vertex_d_object()const{ return Construct_max_vertex_d(*this); } Construct_weighted_point_d construct_weighted_point_d_object()const{ return Construct_weighted_point_d(*this); } - Point_weight_d point_weight_d_object()const{ return Point_weight_d(*this); } + Compute_weight_d compute_weight_d_object()const{ return Compute_weight_d(*this); } Point_drop_weight_d point_drop_weight_d_object()const{ return Point_drop_weight_d(*this); } // Dummies for those required functors missing a concept. diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index a6c73673be0..257401cb907 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -144,7 +144,7 @@ void test2(){ typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; typedef typename K1::Point_drop_weight_d PDW; - typedef typename K1::Point_weight_d PW; + typedef typename K1::Compute_weight_d PW; CGAL_USE_TYPE(AT); CGAL_USE_TYPE(D); @@ -210,7 +210,7 @@ void test2(){ PC pc Kinit(power_center_d_object); CWP cwp Kinit(construct_weighted_point_d_object); PDW pdw Kinit(point_drop_weight_d_object); - PW pw Kinit(point_weight_d_object); + PW pw Kinit(compute_weight_d_object); PoD pod Kinit(power_distance_d_object); CGAL_USE(bc); @@ -630,12 +630,12 @@ void test3(){ typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; typedef typename K1::Point_drop_weight_d PDW; - typedef typename K1::Point_weight_d PW; + typedef typename K1::Compute_weight_d PW; typedef typename K1::Power_side_of_power_sphere_d PT; typedef typename K1::In_flat_power_side_of_power_sphere_d IFPT; CWP cwp Kinit(construct_weighted_point_d_object); PDW pdw Kinit(point_drop_weight_d_object); - PW pw Kinit(point_weight_d_object); + PW pw Kinit(compute_weight_d_object); PT pt Kinit(power_side_of_power_sphere_d_object); IFPT ifpt Kinit(in_flat_power_side_of_power_sphere_d_object); WP wp; diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index d313caa5f03..6840fdbb757 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -46,7 +46,7 @@ A function object that must provide the operator `FT operator()(const Weighted_point_d & wp)`, returning the weight of `wp`. */ -typedef unspecified_type Point_weight_d; +typedef unspecified_type Compute_weight_d; /*! A predicate object that must provide the templated operator @@ -120,7 +120,7 @@ Point_drop_weight_d point_drop_weight_d_object() const; /*! */ -Point_weight_d point_weight_d_object() const; +Compute_weight_d compute_weight_d_object() const; /*! diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 892819ab3b2..192229c9bcf 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -56,7 +56,7 @@ output_weighted_point(std::ostream & os, const Traits &traits, const P & p, typedef typename Traits::Compute_coordinate_d Ccd; typename Traits::Point_drop_weight_d drop_w = traits.point_drop_weight_d_object(); - typename Traits::Point_weight_d pt_weight = traits.point_weight_d_object(); + typename Traits::Compute_weight_d pt_weight = traits.compute_weight_d_object(); const Ccd ccd = traits.compute_coordinate_d_object(); const int dim = traits.point_dimension_d_object()(p); if (dim > 0) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index e1996b39bca..111c6ac9441 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -811,8 +811,8 @@ Regular_triangulation case Base::ON_VERTEX: { Vertex_handle v = s->vertex(f.index(0)); - typename RTTraits::Point_weight_d pw = - geom_traits().point_weight_d_object(); + typename RTTraits::Compute_weight_d pw = + geom_traits().compute_weight_d_object(); if (pw(p) == pw(v->point())) return v; @@ -916,8 +916,8 @@ Regular_triangulation case Base::ON_VERTEX: { Vertex_handle v = s->vertex(f.index(0)); - typename RTTraits::Point_weight_d pw = - geom_traits().point_weight_d_object(); + typename RTTraits::Compute_weight_d pw = + geom_traits().compute_weight_d_object(); if (pw(p) == pw(v->point())) return v; // If dim == 0 and the new point has a bigger weight, diff --git a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h index f88a32ba417..4910b4346e8 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h +++ b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h @@ -51,7 +51,7 @@ public: typedef typename K::Point_d Bare_point_d; typedef typename K::Weighted_point_d Weighted_point_d; typedef typename K::Point_drop_weight_d Point_drop_weight_d; - typedef typename K::Point_weight_d Point_weight_d; + typedef typename K::Compute_weight_d Compute_weight_d; typedef typename K::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; typedef typename K::In_flat_power_side_of_power_sphere_d In_flat_power_side_of_power_sphere_d; From bcf9d7d051c5e91bad65b782dc8c4a9dc8c68a6e Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 22 Sep 2016 16:28:47 +0200 Subject: [PATCH 477/487] Fold Point_drop_weight_d into Construct_point_d. Old name kept temporarily until Triangulation is updated. For the record, I don't like this change. --- .../CGAL/NewKernel_d/Kernel_d_interface.h | 42 ++++++++++++++++++- NewKernel_d/test/NewKernel_d/Epick_d.cpp | 12 ++++-- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index 6983f641841..dd88800579c 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -79,7 +79,47 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Scaled_vector_d; typedef typename Get_functor::type Difference_of_vectors_d; typedef typename Get_functor::type Difference_of_points_d; - typedef typename Get_functor >::type Construct_point_d; + //typedef typename Get_functor >::type Construct_point_d; + struct Construct_point_d : private Store_kernel { + typedef Kernel R_; // for the macro + CGAL_FUNCTOR_INIT_STORE(Construct_point_d) + typedef typename Get_functor >::type CP; + typedef Point_d result_type; + Point_d operator()(Weighted_point_d const&wp)const{ + return typename Get_functor::type(this->kernel())(wp); + } +#ifdef CGAL_CXX11 + Point_d operator()(Weighted_point_d &wp)const{ + return typename Get_functor::type(this->kernel())(wp); + } + Point_d operator()(Weighted_point_d &&wp)const{ + return typename Get_functor::type(this->kernel())(std::move(wp)); + } + Point_d operator()(Weighted_point_d const&&wp)const{ + return typename Get_functor::type(this->kernel())(std::move(wp)); + } + template +# if __cplusplus >= 201402L + decltype(auto) +# else + Point_d +# endif + operator()(T&&...t)const{ + return CP(this->kernel())(std::forward(t)...); + //return CP(this->kernel())(t...); + } +#else +# define CGAL_CODE(Z,N,_) template \ + Point_d operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t))const{ \ + return CP(this->kernel())(BOOST_PP_ENUM_PARAMS(N,t)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +# undef CGAL_CODE + Point_d operator()()const{ \ + return CP(this->kernel())(); \ + } +#endif + }; typedef typename Get_functor >::type Construct_vector_d; typedef typename Get_functor >::type Construct_segment_d; typedef typename Get_functor >::type Construct_sphere_d; diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 257401cb907..bed06b20a03 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -143,7 +143,8 @@ void test2(){ typedef typename K1::Power_distance_d PoD; typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; - typedef typename K1::Point_drop_weight_d PDW; + //typedef typename K1::Point_drop_weight_d PDW; + typedef CP PDW; typedef typename K1::Compute_weight_d PW; CGAL_USE_TYPE(AT); @@ -209,7 +210,8 @@ void test2(){ TP tp Kinit(translated_point_d_object); PC pc Kinit(power_center_d_object); CWP cwp Kinit(construct_weighted_point_d_object); - PDW pdw Kinit(point_drop_weight_d_object); + //PDW pdw Kinit(point_drop_weight_d_object); + PDW const& pdw = cp; PW pw Kinit(compute_weight_d_object); PoD pod Kinit(power_distance_d_object); @@ -629,12 +631,14 @@ void test3(){ typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; - typedef typename K1::Point_drop_weight_d PDW; + //typedef typename K1::Point_drop_weight_d PDW; + typedef CP_ PDW; typedef typename K1::Compute_weight_d PW; typedef typename K1::Power_side_of_power_sphere_d PT; typedef typename K1::In_flat_power_side_of_power_sphere_d IFPT; CWP cwp Kinit(construct_weighted_point_d_object); - PDW pdw Kinit(point_drop_weight_d_object); + //PDW pdw Kinit(point_drop_weight_d_object); + PDW const& pdw = cp_; PW pw Kinit(compute_weight_d_object); PT pt Kinit(power_side_of_power_sphere_d_object); IFPT ifpt Kinit(in_flat_power_side_of_power_sphere_d_object); From e4e781e044854323eebf5d086f97d7b3d5f86313 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 22 Sep 2016 17:53:27 +0200 Subject: [PATCH 478/487] Point_drop_weight_d => Construct_point_d --- .../Concepts/RegularTriangulationTraits.h | 9 +--- .../CGAL/IO/Triangulation_off_ostream.h | 4 +- .../Regular_triangulation_traits_adapter.h | 44 +++++++++---------- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h index 6840fdbb757..ca0e3a0d9cd 100644 --- a/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h +++ b/Triangulation/doc/Triangulation/Concepts/RegularTriangulationTraits.h @@ -29,17 +29,12 @@ The weighted point type. */ typedef unspecified_type Weighted_point_d; -/*! -The (un-weighted) point type. -*/ -typedef unspecified_type Bare_point_d; - /*! A function object that must provide the operator `Point_d operator()(const Weighted_point_d & wp)`, returning `wp` without its weight. */ -typedef unspecified_type Point_drop_weight_d; +typedef unspecified_type Construct_point_d; /*! A function object that must provide the operator @@ -115,7 +110,7 @@ RegularTriangulationTraits(); /*! */ -Point_drop_weight_d point_drop_weight_d_object() const; +Construct_point_d construct_point_d_object() const; /*! diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 192229c9bcf..d6333d4e6d4 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -54,8 +54,8 @@ output_weighted_point(std::ostream & os, const Traits &traits, const P & p, bool output_weight = true) { typedef typename Traits::Compute_coordinate_d Ccd; - typename Traits::Point_drop_weight_d drop_w = - traits.point_drop_weight_d_object(); + typename Traits::Construct_point_d cp = + traits.construct_point_d_object(); typename Traits::Compute_weight_d pt_weight = traits.compute_weight_d_object(); const Ccd ccd = traits.compute_coordinate_d_object(); const int dim = traits.point_dimension_d_object()(p); diff --git a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h index 4910b4346e8..78bb95a60aa 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h +++ b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h @@ -50,7 +50,7 @@ public: // Required by RegularTriangulationTraits typedef typename K::Point_d Bare_point_d; typedef typename K::Weighted_point_d Weighted_point_d; - typedef typename K::Point_drop_weight_d Point_drop_weight_d; + typedef typename K::Construct_point_d Construct_point_d; typedef typename K::Compute_weight_d Compute_weight_d; typedef typename K::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; typedef typename K::In_flat_power_side_of_power_sphere_d @@ -74,8 +74,8 @@ public: result_type operator()( Weighted_point_d const& p, Weighted_point_d const& q, int i) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - return m_kernel.less_coordinate_d_object() (pdw(p), pdw(q), i); + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.less_coordinate_d_object() (cp(p), cp(q), i); } }; @@ -95,10 +95,10 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Construct_point_d cp = m_kernel.construct_point_d_object(); return m_kernel.orientation_d_object() ( - boost::make_transform_iterator(start, pdw), - boost::make_transform_iterator(end, pdw) + boost::make_transform_iterator(start, cp), + boost::make_transform_iterator(end, cp) ); } }; @@ -119,10 +119,10 @@ public: template result_type operator()(ForwardIterator start, ForwardIterator end) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Construct_point_d cp = m_kernel.construct_point_d_object(); return m_kernel.construct_flat_orientation_d_object() ( - boost::make_transform_iterator(start, pdw), - boost::make_transform_iterator(end, pdw) + boost::make_transform_iterator(start, cp), + boost::make_transform_iterator(end, cp) ); } }; @@ -145,11 +145,11 @@ public: result_type operator()(Flat_orientation_d orient, ForwardIterator start, ForwardIterator end) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Construct_point_d cp = m_kernel.construct_point_d_object(); return m_kernel.in_flat_orientation_d_object() ( orient, - boost::make_transform_iterator(start, pdw), - boost::make_transform_iterator(end, pdw) + boost::make_transform_iterator(start, cp), + boost::make_transform_iterator(end, cp) ); } }; @@ -171,11 +171,11 @@ public: result_type operator()(ForwardIterator start, ForwardIterator end, const Weighted_point_d & p) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); + Construct_point_d cp = m_kernel.construct_point_d_object(); return m_kernel.contained_in_affine_hull_d_object() ( - boost::make_transform_iterator(start, pdw), - boost::make_transform_iterator(end, pdw), - pdw(p) + boost::make_transform_iterator(start, cp), + boost::make_transform_iterator(end, cp), + cp(p) ); } }; @@ -196,8 +196,8 @@ public: result_type operator()( const Weighted_point_d & p, const Weighted_point_d & q) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - return m_kernel.compare_lexicographically_d_object()(pdw(p), pdw(q)); + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.compare_lexicographically_d_object()(cp(p), cp(q)); } }; @@ -217,8 +217,8 @@ public: result_type operator()( const Weighted_point_d & p, const int i) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - return m_kernel.compute_coordinate_d_object()(pdw(p), i); + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.compute_coordinate_d_object()(cp(p), i); } }; @@ -239,8 +239,8 @@ public: result_type operator()( const Weighted_point_d & p) const { - Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - return m_kernel.point_dimension_d_object()(pdw(p)); + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.point_dimension_d_object()(cp(p)); } }; From de1cb153feb12885c55fc85b5238cdda0a1b2e76 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 23 Sep 2016 08:36:39 +0200 Subject: [PATCH 479/487] Remove Convex_hull.h from here since it's been deleted --- Triangulation/dont_submit | 1 - 1 file changed, 1 deletion(-) diff --git a/Triangulation/dont_submit b/Triangulation/dont_submit index b2de9879971..1333ed77b7e 100644 --- a/Triangulation/dont_submit +++ b/Triangulation/dont_submit @@ -1,2 +1 @@ TODO -include/CGAL/Convex_hull.h From e7470160201adc6ceb2d768c63f9a98f716cda19 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 23 Sep 2016 08:47:45 +0200 Subject: [PATCH 480/487] Remove TODO (everything has been done) and dont_submit as it's empty now --- Triangulation/TODO | 254 -------------------------------------- Triangulation/dont_submit | 1 - 2 files changed, 255 deletions(-) delete mode 100644 Triangulation/TODO delete mode 100644 Triangulation/dont_submit diff --git a/Triangulation/TODO b/Triangulation/TODO deleted file mode 100644 index 64a961313bd..00000000000 --- a/Triangulation/TODO +++ /dev/null @@ -1,254 +0,0 @@ - --------------------------------------------------- -Problems to be solved from Sam's reading (september 2012) --------------------------------------------------- - -*) Substitute iterator : it seems to be comparing the point directly, instead -of comparing the iterator. That look like a big performance killer. - -*) I have marked with 'FIXME' all the lines where the code assumes, or seems to -assume that the vertex at infinity is at index 0 in the full cell. The code is -still working because the vertex at infinity is indeed at index 0, but this is -no more a requirement from the documentation, so that the code (Tr.h and -Delaunay_tr.h) should be changed. OR, we re-document 0 as the index of the -vertex at infinity. - - - -ALL Remarks below are done or not important - - --------------------------------------------------- -Problems to be solved from the reviews (beginning 2012) --------------------------------------------------- - -example delaunay does not execute properly - - SAM: seems to be a compiler bug --> low priority. - OD: I am afraid that it is still some strange bug in the code that show up only in - some compilation circumstances. - running both delaunay compiled debug/release, the diverges after the 6th insertion (in 2d round) - -in Triangulation_data_structure : -put a default value for dim in the constructor -(does not work, I do not understand why). OK done. - - SAM: I've modified the Concept constructor's documentation to reflect this. - If it is not satisfying, we might remove this doc. from the Concept and - move it to the class documentation. - -check that the perturbation scheme is independant of the order of insertion - - SAM: It is your and Monique's scheme. It should be independent, which - is a requirement anyway for the Delaunay::remove() function to work - properly. - OD: seems ok, lexicographic order. - -Add a template parameter Location_policy - -ambient dim vs max dim - OD: global replace done, remains to get the dim from the traits (and not from the point of the traits) - -check all is_valid function, precise in the doc what they are doing. -(do sth like 2/3 d) - - SAM: I suggest that the documentation of the function in the concepts only - states that "any validity check can be performed here (see model doc. for - details)", and that we re document the same function in the class documentation - with details on what exactly is performed by the implementation. - OD: seems reasonable - SAM: I've changed my mind a little. We need some easy mandatory checks in - concepts T...DSFullCell and T...DSVertex so that we can rely on these tests in - the implementation of T.._data_structure, instead of having to re-implement them. - So : the concepts lists simple validity checks taht must be present, and refers - to the documentation of the models for possible additional validity checks - that are implemented. - --> This scheme is done (code&doc) for TDS TDSFullCell and TDSVertex and Triangulation. - --> ALL DONE. - -small feature with iterator "all tuples" - -make the code and doc agree on Flat_* stuff (orientation in a flat) - -iterator on points in concept TriangulationVertex should be removed to keep requirements minimal - - REMOVED: But this makes the concept TriangulationFullCell empty and useless. - -make doc of TDS-FullCellStoragePolicy in user manual - - DONE. - -missing figures : Triangulation/fig/detail.png Triangulation/fig/illustration.png - - - - - - - - - --------------------------------------------------- -Old todo list (beginning 2011) --------------------------------------------------- -Les premiers points meritent d'etre examinés - -Je me replonge dans Triangulation en dim d - -ma liste de trucs à faire ou questions à résoudre: - - ---- Constructeur de triangulation - prévoir un constructeur qui prends d+1 points en position générale - ---- Doc 1.5 à faire - - ---- mirror_index - - policy a ajouter dans le user manual - - le code ne fait pas ce qui est dit dans la doc (ça ne retourne pas -1) - - PS: Samuel tu as benché la policy ? ça vaut vraiment la peine de s'embeter avec ça ? - - ---- Face - - pourquoi une face ne pourrait pas être de pleine dimension ? - c'est pas la peine d'avoir un truc générique pour les faces de toutes dim sauf un - OD: J'ai propose de viré cette restriction dans la doc, mais il faudrait vérifier le code. - - ---- TriangulationTraits et DelaunayTraits - lower dimensional predicates - le truc de l'orientation "consistante"est quand même un peu délicat - - d'une part, je proposerai un truc du genre: le noyau doit fournir un iterateur - de points en position générale - (un truc fixe, ça donne toujours les mêmes points e.g. l'origine et les points - avec une coordonnée à 1 et les autres à 0). - Ce générateur permet donc de compléter tout ensemble de points pour obtenir - des points en position générale. - - d'autre part ???? il faut un minimum en plus pour qu'on comprenne que - l'orientation du sous-espace est stocké qq part. - ---- TriangulationTraits has models - ... il faut voir ce que l'on met vraiment. - ---- Marque visité. - elle devrait etre dans le concept TDSFullCell - --------------------------------------------------- -ci dessous les points ont deja etes traites - ---- Index du sommet à l'infini. - Il est en ce moment prévu que le sommet à l'infini est l'index 0 dans les full - cell où il apparraît. Ça me semble très discutable, en particulier la tds ne sait - pas qui est à l'infini, et donc comment peut-elle garantir dans une manipulation - que toutes les cellules crées ou modifiées vont préserver cette position. - - je suis donc pour virer ce truc ce qui implique des modifs dans la doc - (1.3 - ? p54) et dans le code. - - en plus il y a des trucs pas cohérent, i.e. p. 50 dans la doc de locate - l'infini est en dernier, pas en premier. - - finite_vertex_iterator marche pas - SAM: J'ai corrigé le problème, mais c'est pas super propre. Le problème - vient de boost::filter_iterator qui suppose que le prédicat de filtrage - prend en argument |const value_type &| plutôt que |iterator|. Mais - quand on veut tester si un sommet est infini, on a envie de comparer - les iterator (ou handle)... ce qui n'est pas possible avec le - filter_iterator de boost. (Le filter_iterator de CGAL appele le - prédicat de filtrage sur l'itérateur, et non pas sur la valeur vers - lequel il pointe, comme le fait boost. Mais je ne sais pas si le filtre - d'iterateur de CGAL est destiné à durer) - - ---- Orientation des cellules. - les cellules sont orientées positivement par convention - - le dire dans la doc (deux full cell partagent une facet, elles doivent avoir - des orientation complémentaires - - dans Triangulation, il faut virer la méthode "orientation" - (ou au minimum, la mettre advanced) - ---- Triangulation is_infinite - j'avais viré les préconditions, et je maintiens. - en dim 0 on a une full cell finie et une infinie - en dim 1 on a 2 full cell infinie, 1 vertex/facet infini - et ok, en d=0, facet n'a pas de sens, mais l'utilisateur aura du mal a en avoir une - ---- Triangulation fonctions incident_* et star - est-il nécessaire de reprendre leur doc? (on pourrait pointer sur celle de TDS) - au moins pour incident_upper_faces - ---- dans Triangulation_data_structure.h insert_in_tagged_hole - on a l'air de supposer que full_cell(f) est marqué visité - (pourquoi ça serait pas l'autre représentation de la Facet f ?) - la doc de TDS::insert_in_hole est maintenant claire - - - - - - - -Older todo list (2010 ?) -__________________________________________________________________________RENAMING - -*) doc : --------- - -*) code not done : ------------------- - -bring part of Delaunay::remove into TDS (see comments in Delaunay_triangulation.h, and item FUTURE below) - -__________________________________________________________________________ALL - -*) FUTURE: better system for simplex's flags to know if we can use them or not - in Delaunay_triangulation::remove(Vertex_handle) - -_________________________________________________TRIANGULATION_DATA_STRUCTURE - -*) Un-recursify insert_in_tagged_hole : crashed in dimension 8 : stack overflow. - -*) TriangulationDataStructure: - - Should we put >> and << in the documentation of the class - Triangulation_data_structure ? - -*) Triangulation_data_structure.h: - - Ensure that it is topologically possible to collapse the Face in - collapse_face(Face) - -*) TriangulationDSVertex - - Should we put >> and << in the documentation of the class - Triangulation_ds_vertex instead of in that of the concept ? - -*) TDSFullCellStoragePolicy - what is it ? => see the doc. - it is undocumented. => it is documented (Triangulation_ds_full_cell) - if the aim is to choose between "full representation" and "1-skeleton" - I would prefer a different TDS class, at least the doc has to rewriten a sentence - like "class TDS explicitely stores its vertices and full cells" - does not apply to 1-skeleton representation - => no, this has nothing to do with 1-skeleton. - -*) default dim parameter in constructor (especially in the static case) -done - -________________________________________________________________TRIANGULATION - -*) default dim parameter in constructor (especially in the static case) -done - -*) Why vertex at infinity should have index 0 in all cells it appears ? - This is a convention that is enforced throughout the code. Makes it faster - to check for an infinite cell. - The "old" package "Convex_hull_d" does the same. -done - -_______________________________________________________DELAUNAY_TRIANGULATION - -________________________________________________________REGULAR_TRIANGULATION - -*) write Regular_triangulation.h (!) -*) write RegularTriangulationTraits.tex -*) write Regular_triangulation.tex diff --git a/Triangulation/dont_submit b/Triangulation/dont_submit deleted file mode 100644 index 1333ed77b7e..00000000000 --- a/Triangulation/dont_submit +++ /dev/null @@ -1 +0,0 @@ -TODO From 3704a594223bc0f6738ca45d6eb6cb5dd2130d2c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Sep 2016 18:13:20 +0200 Subject: [PATCH 481/487] Fix warning (unused types and variables) --- Triangulation/include/CGAL/IO/Triangulation_off_ostream.h | 2 -- Triangulation/include/CGAL/Triangulation.h | 1 - 2 files changed, 3 deletions(-) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index d6333d4e6d4..701f08202cd 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -207,9 +207,7 @@ export_triangulation_to_off(std::ostream & os, { typedef Triangulation Tr; typedef typename Tr::Vertex_const_handle Vertex_handle; - typedef typename Tr::Vertex_const_iterator Vertex_iterator; typedef typename Tr::Finite_vertex_const_iterator Finite_vertex_iterator; - typedef typename Tr::Full_cell_const_handle Full_cell_handle; typedef typename Tr::Finite_full_cell_const_iterator Finite_full_cell_iterator; typedef typename Tr::Full_cell_const_iterator Full_cell_iterator; typedef typename Tr::Full_cell Full_cell; diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 49170a62380..906df92e004 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -919,7 +919,6 @@ Triangulation // infinite one... CGAL_precondition( is_infinite(s) ); CGAL_precondition( 1 == current_dimension() ); - int inf_v_index = s->index(infinite_vertex()); Vertex_handle v = tds().insert_in_full_cell(s); v->set_point(p); return v; From 0c3cb6a19d1307f317a94a9569c1c50705de229f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Jan 2017 16:35:39 +0100 Subject: [PATCH 482/487] Update and clarify complexity --- .../doc/Triangulation/Triangulation.txt | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index b4ac0504e0e..12c63333fd2 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -508,16 +508,18 @@ This simple example shows how to create a regular triangulation. \section TriangulationSecPerf Complexity and Performances -When inserting a set of points into a Delaunay triangulation, -the current implementation starts -by spatially sorting the points. Then, for each point to insert, -it locates it by walking in the triangulation, using the -previously inserted vertex as a "hint". Finally, the point is +When inserting a batch of points into a Delaunay triangulation, +the current implementation starts by spatially sorting the points. +Then, for each point to insert, it locates it by walking in the triangulation, +using the previously inserted vertex as a "hint". Finally, the point is inserted. -In the worst case, the expected complexity is -\f$ O(n^{\lceil\frac{d}{2}\rceil}+n\log n)\f$. When the algorithm is -run on \f$ n \f$ random points, the cost of inserting one point is -\f$ O(n^{1/d}) \f$. +In the worst case scenario, without spatial sort, the expected complexity is +\f$ O(n^{\lceil\frac{d}{2}\rceil+1}) \f$. +When the algorithm is run on uniformly distributed points, the localization complexity is +\f$ O(n^{\frac{1}{d}}) \f$ and the size of the triangulation is \f$ O(n) \f$, which gives +a complexity of \f$ O(n^{1+\frac{1}{d}}) \f$ for the insertion. +With spatial sort and random points, one can expect a complexity of \f$ O(n\log n) \f$. +Please refer to \cgalCite{boissonnat2009Delaunay} for more details. We provide below (\cgalFigureRef{Triangulationfigbenchmarks100}, \cgalFigureRef{Triangulationfigbenchmarks1000} and From ebc4605d3ecfb0f50b8f1907676d834b59a718b7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Jan 2017 17:43:27 +0100 Subject: [PATCH 483/487] Fix authors --- Documentation/doc/biblio/geom.bib | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/doc/biblio/geom.bib b/Documentation/doc/biblio/geom.bib index 054630adb6b..340f1d0655c 100644 --- a/Documentation/doc/biblio/geom.bib +++ b/Documentation/doc/biblio/geom.bib @@ -151979,7 +151979,7 @@ pages = {179--189} @inproceedings{boissonnat2009Delaunay, TITLE = {{Incremental construction of the Delaunay graph in medium dimension}}, - AUTHOR = {Boissonnat, Jean-Daniel and Devillers, Olivier OD and Hornus, Samuel}, + AUTHOR = {Boissonnat, Jean-Daniel and Devillers, Olivier and Hornus, Samuel}, URL = {https://hal.inria.fr/inria-00412437}, BOOKTITLE = {{Annual Symposium on Computational Geometry}}, ADDRESS = {Aarhus, Denmark}, @@ -151989,4 +151989,4 @@ pages = {179--189} PDF = {https://hal.inria.fr/inria-00412437/file/socg09.pdf}, HAL_ID = {inria-00412437}, HAL_VERSION = {v1}, -} \ No newline at end of file +} From a1a60e9921796dc2c3ed276511f3824e5e960ca1 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Jan 2017 17:44:46 +0100 Subject: [PATCH 484/487] Fix typos --- Triangulation/doc/Triangulation/CGAL/Triangulation.h | 3 ++- Triangulation/doc/Triangulation/Triangulation.txt | 11 +++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Triangulation.h b/Triangulation/doc/Triangulation/CGAL/Triangulation.h index 9f198797dd9..bf01cfdce74 100644 --- a/Triangulation/doc/Triangulation/CGAL/Triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Triangulation.h @@ -214,7 +214,8 @@ type (a signed integral type) typedef TriangulationDataStructure_::difference_type difference_type; /*! -\enum used by `Triangulation` to specify which case occurs when locating a point in the triangulation +\enum Locate_type +\brief Used by `Triangulation` to specify which case occurs when locating a point in the triangulation. */ enum Locate_type { ON_VERTEX=0, /*!< when the located point coincides with a vertex of the triangulation */ IN_FACE, /*!< when the point is in the interior of a face of dimension equal or less than `maximal_dimension()` - 2 */ diff --git a/Triangulation/doc/Triangulation/Triangulation.txt b/Triangulation/doc/Triangulation/Triangulation.txt index 12c63333fd2..962ec2bfe97 100644 --- a/Triangulation/doc/Triangulation/Triangulation.txt +++ b/Triangulation/doc/Triangulation/Triangulation.txt @@ -117,7 +117,7 @@ triangulation data structure and can then be obtained using the method `tds.maxi A triangulation data structure also knows the current dimension of its full cells, which can be obtained using `tds.current_dimension()`. In the sequel, let us denote the maximal dimension with \f$ D \f$ and the current dimension with \f$ d \f$. -The inequalities \f$ -2 \leq d \leq D\f$ and \f$ 0 \le D\f$ always hold. +The inequalities \f$ -2 \leq d \leq D\f$ and \f$ 0 < D\f$ always hold. The special meaning of negative values for \f$d\f$ is explained below. ## The Set of Faces ## @@ -453,22 +453,21 @@ Let \f$ {S}^{(w)}\f$ be a set of weighted points in \f$ \mathbb{R}^D\f$. Let \f$ {p}^{(w)}=(p,w_p), p\in\mathbb{R}^D, w_p\in\mathbb{R}\f$ and \f$ {z}^{(w)}=(z,w_z), z\in\mathbb{R}^D, w_z\in\mathbb{R}\f$ be two weighted points. -If all weights are positive, a weighted point -\f$ {p}^{(w)}=(p,w_p)\f$ can also be seen as a sphere of center \f$ p\f$ and -radius \f$ \sqrt{w_p}\f$. +A weighted point \f$ {p}^{(w)}=(p,w_p)\f$ can also be seen as a sphere of +center \f$ p\f$ and radius \f$ \sqrt{w_p}\f$. The power product (or power distance ) between \f$ {p}^{(w)}\f$ and \f$ {z}^{(w)}\f$ is defined as \f[ \Pi({p}^{(w)},{z}^{(w)}) = {\|{p-z}\|^2-w_p-w_z} \f] where \f$ \|{p-z}\|\f$ is the Euclidean distance between \f$ p\f$ and \f$ z\f$. \f$ {p}^{(w)}\f$ and \f$ {z}^{(w)}\f$ -are said to be orthogonal if \f$ \Pi{({p}^{(w)}-{z}^{(w)})} +are said to be orthogonal if \f$ \Pi({p}^{(w)},{z}^{(w)}) = 0\f$. \f$D + 1\f$ weighted points have a unique common orthogonal weighted point called the power sphere. A sphere \f$ {z}^{(w)}\f$ is said to be regular if \f$ \forall {p}^{(w)}\in{S}^{(w)}, -\Pi{({p}^{(w)}-{z}^{(w)})}\geq 0\f$. +\Pi({p}^{(w)},{z}^{(w)})\geq 0\f$. A triangulation of \f$ {S}^{(w)}\f$ is regular if the power spheres of all simplices are regular. From d59445394fc23ee775b2c72a9f490081c198fc7b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Jan 2017 17:46:24 +0100 Subject: [PATCH 485/487] Improve sentence --- Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h index 0e885c5a659..c22ed0d7e17 100644 --- a/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h +++ b/Triangulation/doc/Triangulation/CGAL/Regular_triangulation.h @@ -111,8 +111,8 @@ Vertex_handle insert(const Weighted_point & p, Locate_type lt, /*! Inserts the weighted points found in range `[s,e)` in the regular triangulation. -Returns the difference of the number of vertices between after and -before the insertions (it may be negative due to hidden points). +Returns the difference between the number of vertices after and before +the insertions (it may be negative due to hidden points). Note that this function is not guaranteed to insert the points following the order of `ForwardIterator` because `spatial_sort()` is used to improve efficiency. From 9275cbc2046db9de89e813e8ea81fde97e006afa Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 10 Jan 2017 11:33:42 +0100 Subject: [PATCH 486/487] struct -> class+public --- Kernel_d/doc/Kernel_d/CGAL/Epick_d.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h index 585ffc20773..7d91973363e 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h @@ -94,7 +94,8 @@ double weight() const; /*! \cgalModels `Kernel_d::Center_of_sphere_d` */ -struct Construct_circumcenter_d { +class Construct_circumcenter_d { +public: /*! returns the center of the sphere defined by `A=tuple[first,last)`. The sphere is centered in the affine hull of A and passes through all the points of A. The order of the points of A does not matter. \pre A is affinely independant. \tparam ForwardIterator has `Epick_d::Point_d` as value type. @@ -102,7 +103,8 @@ struct Construct_circumcenter_d { template Point_d operator()(ForwardIterator first, ForwardIterator last); }; -struct Compute_squared_radius_d { +class Compute_squared_radius_d { +public: /*! returns the radius of the sphere defined by `A=tuple[first,last)`. The sphere is centered in the affine hull of A and passes through all the points of A. The order of the points of A does not matter. \pre A is affinely independant. \tparam ForwardIterator has `Epick_d::Point_d` as value type. @@ -112,7 +114,8 @@ Point_d operator()(ForwardIterator first, ForwardIterator last); }; /*! \cgalModels `Kernel_d::Side_of_bounded_sphere_d` */ -struct Side_of_bounded_sphere_d { +class Side_of_bounded_sphere_d { +public: /*! returns the relative position of point p to the sphere defined by `A=tuple[first,last)`. The sphere is centered in the affine hull of A and passes through all the points of A. The order of the points of A does not matter. \pre A is affinely independant. \tparam ForwardIterator has `Epick_d::Point_d` as value type. From 8b90573da4bf45c53032cc00019f179d1e3186a8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 16 Jan 2017 10:56:14 +0100 Subject: [PATCH 487/487] Spatial_searching was missing --- Kernel_d/doc/Kernel_d/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Kernel_d/doc/Kernel_d/dependencies b/Kernel_d/doc/Kernel_d/dependencies index fdf381a7a17..eea7200c3d4 100644 --- a/Kernel_d/doc/Kernel_d/dependencies +++ b/Kernel_d/doc/Kernel_d/dependencies @@ -6,4 +6,4 @@ Circulator Stream_support Number_types Triangulation - +Spatial_searching