summaryrefslogtreecommitdiff
path: root/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h
blob: a8896976abec9b6ca6f5a9fe88ddc56a2a80dc83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// 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_KERNEL_D_CARTESIAN_CONVERTER_H
#define CGAL_KERNEL_D_CARTESIAN_CONVERTER_H

#include <CGAL/basic.h>
#include <CGAL/tuple.h>
#include <CGAL/typeset.h>
#include <CGAL/Object.h>
#include <CGAL/Origin.h>
#include <CGAL/NT_converter.h>
#include <CGAL/NewKernel_d/functor_tags.h>
#include <CGAL/Kernel/mpl.h>
#include <CGAL/is_iterator.h>
#include <CGAL/transforming_iterator.h>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/if.hpp>
#include <CGAL/NewKernel_d/store_kernel.h>
#include <CGAL/NewKernel_d/Kernel_object_converter.h>

namespace CGAL {
namespace internal {
// Reverses order, but that shouldn't matter.
template<class K,class T> struct Map_taglist_to_typelist :
  Map_taglist_to_typelist<K,typename T::tail>::type
  ::template add<typename Get_type<K, typename T::head>::type>
{};
template<class K> struct Map_taglist_to_typelist<K,typeset<> > : typeset<> {};
}

template<class List = typeset<> >
struct Object_converter {
	typedef Object result_type;
	template<class F>
	result_type operator()(Object const& o, F const& f) const {
	  typedef typename List::head H;
		if (H const* ptr = object_cast<H>(&o))
			return make_object(f(*ptr));
		else
			return Object_converter<typename List::tail>()(o,f);
	}
};
template<>
struct Object_converter <typeset<> > {
	typedef Object result_type;
	template<class F>
	result_type operator()(Object const&,F const&)const {
		CGAL_error_msg("Cartesiand_converter is unable to determine what is wrapped in the Object");
		return Object();
	}
};


	//TODO: special case when K1==K2 (or they are very close?)
template<class Final_, class K1, class K2, class List>
class KernelD_converter_
: public KernelD_converter_<Final_,K1,K2,typename List::tail>
{
	typedef typename List::head Tag_;
	typedef typename List::tail Rest;
	typedef KernelD_converter_<Final_,K1,K2,Rest> Base;
	typedef typename Get_type<K1,Tag_>::type K1_Obj;
	typedef typename Get_type<K2,Tag_>::type K2_Obj;
	typedef typename Get_functor<K1, Convert_ttag<Tag_> >::type K1_Conv;
	typedef KO_converter<Tag_,K1,K2> KOC;
	typedef CGAL_BOOSTD is_same<K1_Conv, Null_functor> no_converter;
	typedef typename internal::Map_taglist_to_typelist<K1,Rest>::type::template contains<K1_Obj> duplicate;

	// Disable the conversion in some cases:
	struct Do_not_use{};

        // Explicit calls to boost::mpl functions to avoid parenthesis
        // warning on some versions of GCC
	typedef typename boost::mpl::if_ <
                          // If Point==Vector, keep only one conversion
          boost::mpl::or_<boost::mpl::bool_<duplicate::value>,
                          // For iterator objects, the default is make_transforming_iterator
                          boost::mpl::bool_<(iterator_tag_traits<Tag_>::is_iterator && no_converter::value)> >,
	  Do_not_use,K1_Obj>::type argument_type;
	//typedef typename KOC::argument_type K1_Obj;
	//typedef typename KOC::result_type K2_Obj;
	public:
  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);
	}
	K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD false_type)const{
		return K1_Conv(this->myself().kernel())(this->myself().kernel2(),this->myself(),o);
	}
	K2_Obj operator()(argument_type const& o)const{
	  return helper(o,no_converter());
	}
	template<class X,int=0> struct result:Base::template result<X>{};
	template<int i> struct result<Final_(argument_type),i> {typedef K2_Obj type;};
};

template<class Final_, class K1, class K2>
class KernelD_converter_<Final_,K1,K2,typeset<> > {
	public:
	struct Do_not_use2{};
	void operator()(Do_not_use2)const{}
	template<class T> struct result;
	Final_& myself(){return *static_cast<Final_*>(this);}
	Final_ const& myself()const{return *static_cast<Final_ const*>(this);}
};


// TODO: use the intersection of Kn::Object_list.
template<class K1, class K2, class List_=
typename typeset_intersection<typename K1::Object_list, typename K2::Object_list>::type
//typeset<Point_tag>::add<Vector_tag>::type/*::add<Segment_tag>::type*/
> class KernelD_converter
	: public Store_kernel<K1>, public Store_kernel2<K2>,
	public KernelD_converter_<KernelD_converter<K1,K2,List_>,K1,K2,List_>
{
	typedef KernelD_converter Self;
	typedef Self Final_;
	typedef KernelD_converter_<Self,K1,K2,List_> Base;
	typedef typename Get_type<K1, FT_tag>::type FT1;
	typedef typename Get_type<K2, FT_tag>::type FT2;
	typedef NT_converter<FT1, FT2> NTc;
	NTc c; // TODO: compressed storage as this is likely empty and the converter gets passed around (and stored in iterators)

	public:
	KernelD_converter(){}
	KernelD_converter(K1 const&a,K2 const&b):Store_kernel<K1>(a),Store_kernel2<K2>(b){}

	// For boost::result_of, used in transforming_iterator
	template<class T,int i=is_iterator<T>::value?42:0> struct result:Base::template result<T>{};
	template<class T> struct result<Final_(T),42> {
		typedef transforming_iterator<Final_,T> type;
	};
	template<int i> struct result<Final_(K1),i>{typedef K2 type;};
	template<int i> struct result<Final_(int),i>{typedef int type;};
	// Ideally the next 2 would come with Point_tag and Vector_tag, but that's hard...
	template<int i> struct result<Final_(Origin),i>{typedef Origin type;};
	template<int i> struct result<Final_(Null_vector),i>{typedef Null_vector type;};
	template<int i> struct result<Final_(Object),i>{typedef Object type;};
	template<int i> struct result<Final_(FT1),i>{typedef FT2 type;};

	using Base::operator();
	typename Store_kernel2<K2>::reference2_type operator()(K1 const&)const{return this->kernel2();}
	int operator()(int i)const{return i;}
	Origin operator()(Origin const&o)const{return o;}
	Null_vector operator()(Null_vector const&v)const{return v;}
	FT2 operator()(FT1 const&x)const{return c(x);}
	//RT2 operator()(typename First_if_different<RT1,FT1>::Type const&x)const{return cr(x);}

	typename Get_type<K2, Flat_orientation_tag>::type const&
	operator()(typename Get_type<K1, Flat_orientation_tag>::type const&o)const
	{ return o; } // Both kernels should have the same, returning a reference should warn if not.

	template<class It>
	transforming_iterator<Final_,typename boost::enable_if<is_iterator<It>,It>::type>
	operator()(It const& it) const {
		return make_transforming_iterator(it,*this);
	}

	template<class T>
	//TODO: use decltype in C++11 instead of result
	std::vector<typename result<Final_(T)>::type>
	operator()(const std::vector<T>& v) const {
		return std::vector<typename result<Final_(T)>::type>(operator()(v.begin()),operator()(v.begin()));
	}

	//TODO: convert std::list and other containers?

	Object
	operator()(const Object &obj) const
	{
		typedef typename internal::Map_taglist_to_typelist<K1,List_>::type Possibilities;
		//TODO: add Empty, vector<Point>, etc to the list.
		return Object_converter<Possibilities>()(obj,*this);
	}

	//TODO: convert boost::variant

};

} //namespace CGAL

#endif // CGAL_KERNEL_D_CARTESIAN_CONVERTER_H