1 // Copyright (c) 2011 GeometryFactory (France). All rights reserved.
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org)
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Intersections_2/include/CGAL/Intersection_traits.h $
7 // $Id: Intersection_traits.h 209513d 2020-07-31T15:58:38+02:00 Dmitry Anisimov
8 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s) : Philipp Möller
12
13 #ifndef CGAL_INTERSECTION_TRAITS_H
14 #define CGAL_INTERSECTION_TRAITS_H
15
16 #include <CGAL/Kernel_traits.h>
17 #include <CGAL/Object.h>
18 #include <CGAL/assertions.h>
19 #include <CGAL/Dimension.h>
20
21 #include <boost/type_traits/is_same.hpp>
22 #include <boost/variant.hpp>
23
24 #define CGAL_INTERSECTION_TRAITS_2(A, B, R1, R2) \
25 template<typename K> \
26 struct Intersection_traits<K, typename K::A, typename K::B> { \
27 typedef typename boost::variant<typename K::R1, typename K::R2 > \
28 variant_type; \
29 typedef typename boost::optional< variant_type > result_type; \
30 };
31
32 #define CGAL_INTERSECTION_TRAITS_3(A, B, R1, R2, R3) \
33 template<typename K> \
34 struct Intersection_traits<K, typename K::A, typename K::B> { \
35 typedef typename boost::variant<typename K::R1, typename K::R2, \
36 typename K::R3> variant_type; \
37 typedef typename boost::optional< variant_type > result_type; \
38 };
39
40 #define CGAL_INTERSECTION_FUNCTION(A, B, DIM) \
41 template<typename K> \
42 inline \
43 decltype(auto) \
44 intersection(const A<K>& a, const B<K>& b) { \
45 return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
46 } \
47 template<typename K> \
48 inline \
49 decltype(auto) \
50 intersection(const B<K>& a, const A<K>& b) { \
51 return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
52 }
53
54 #define CGAL_INTERSECTION_FUNCTION_SELF(A, DIM) \
55 template<typename K> \
56 inline \
57 decltype(auto) \
58 intersection(const A<K> & a, const A<K> & b) { \
59 return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
60 }
61
62 #define CGAL_DO_INTERSECT_FUNCTION(A, B, DIM) \
63 template<typename K> \
64 inline bool \
65 do_intersect(const A<K>& a, const B<K>& b) { \
66 return BOOST_PP_CAT(K().do_intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
67 } \
68 template<typename K> \
69 inline bool \
70 do_intersect(const B<K>& a, const A<K>& b) { \
71 return BOOST_PP_CAT(K().do_intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
72 }
73
74 #define CGAL_DO_INTERSECT_FUNCTION_SELF(A, DIM) \
75 template<typename K> \
76 inline bool \
77 do_intersect(const A<K> & a, const A<K> & b) { \
78 return BOOST_PP_CAT(K().do_intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
79 }
80
81 namespace CGAL {
82
83 // only declarationn
84 template<typename, typename, typename>
85 struct Intersection_traits {
86 // This defaults to Object, if we use VERSION < 2 and do nothing
87 // otherwise.
88 };
89
90
91 // Alias that gets the Kernel automatically and does some error checking.
92 // Including corresponding specialization for Bbox, as it has no Kernel.
93 template<typename A, typename B>
94 class IT : public Intersection_traits< typename Kernel_traits<A>::Kernel, A, B > {
95 typedef typename Kernel_traits<A>::Kernel A_Kernel;
96 typedef typename Kernel_traits<B>::Kernel B_Kernel;
97 // CGAL_static_assertion_msg( (boost::is_same< A_Kernel, B_Kernel>::value),
98 // "IT instantiated with objects from two different Kernels");
99 };
100
101 class Bbox_2;
102 class Bbox_3;
103
104 template<typename B>
105 class IT<Bbox_2, B> : public Intersection_traits< typename Kernel_traits<B>::Kernel, CGAL::Bbox_2, B >
106 { };
107
108 template<typename B>
109 class IT<Bbox_3, B> : public Intersection_traits< typename Kernel_traits<B>::Kernel, CGAL::Bbox_3, B >
110 { };
111
112
113 namespace Intersections {
114 namespace internal {
115
116 // this function is used to call either make_object or a
117 // Intersection_traits::result_type constructor to create return
118 // values. The Object version takes some dummy template arguments
119 // that are needed for the return of the Intersection_traits. In
120 // theory a one parameter variant could be returned, but this
121 // _could_ come with conversion overhead and so we rather go for
122 // the real type.
123 // Overloads for empty returns are also provided.
124 template<typename F, typename A, typename B, typename T>
decltype(auto)125 decltype(auto)
126 intersection_return(T&& t) { return decltype(std::declval<F>()(std::declval<A>(), std::declval<B>()))(std::forward<T>(t)); }
127 template<typename F, typename A, typename B>
decltype(auto)128 decltype(auto)
129 intersection_return() { return decltype(std::declval<F>()(std::declval<A>(), std::declval<B>()))(); }
130
131 // Something similar to wrap around boost::get and object_cast to
132 // prevent ifdefing too much. Another way could be to introduce an
133 // overload of boost::get for Object. We only provide the pointer
134 // casts here. But use references to const as parameters. This makes
135 // it somewhat nicer.
136 template<typename T>
137 inline
intersect_get(const CGAL::Object & o)138 const T* intersect_get(const CGAL::Object& o) {
139 return CGAL::object_cast<T>(&o);
140 }
141
142 template<typename T, BOOST_VARIANT_ENUM_PARAMS(typename U)>
143 inline
intersect_get(const boost::optional<boost::variant<BOOST_VARIANT_ENUM_PARAMS (U)>> & v)144 const T* intersect_get(const boost::optional< boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)> >& v) {
145 return boost::get<T>(&*v);
146 }
147
148 template<typename T, BOOST_VARIANT_ENUM_PARAMS(typename U)>
149 inline
intersect_get(const boost::variant<BOOST_VARIANT_ENUM_PARAMS (U)> & v)150 const T* intersect_get(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)> & v) {
151 return boost::get<T>(&v);
152 }
153
154 template<typename A, typename B>
decltype(auto)155 decltype(auto)
156 intersection_impl(const A& a, const B& b, CGAL::Dimension_tag<2>) {
157 typedef typename CGAL::Kernel_traits<A>::Kernel Kernel;
158 return Kernel().intersect_2_object()(a, b);
159 }
160
161 template<typename A, typename B>
decltype(auto)162 decltype(auto)
163 intersection_impl(const A& a, const B& b, Dimension_tag<3>) {
164 typedef typename CGAL::Kernel_traits<A>::Kernel Kernel;
165 return Kernel().intersect_3_object()(a, b);
166 }
167
168 template<typename A, typename B>
169 typename Intersection_traits< typename CGAL::Kernel_traits<A>::Kernel, A, B>::result_type
intersection_impl(const A & a,const B & b,Dynamic_dimension_tag)170 intersection_impl(const A& a, const B& b, Dynamic_dimension_tag) {
171 typedef typename CGAL::Kernel_traits<A>::Kernel Kernel;
172 return Kernel().intersect_d_object()(a, b);
173 }
174
175 template<typename A, typename B>
176 inline bool
do_intersect_impl(const A & a,const B & b,CGAL::Dimension_tag<2>)177 do_intersect_impl(const A& a, const B& b, CGAL::Dimension_tag<2>) {
178 typedef typename CGAL::Kernel_traits<A>::Kernel Kernel;
179 return Kernel().do_intersect_2_object()(a, b);
180 }
181
182 template<typename A, typename B>
183 inline bool
do_intersect_impl(const A & a,const B & b,Dimension_tag<3>)184 do_intersect_impl(const A& a, const B& b, Dimension_tag<3>) {
185 typedef typename CGAL::Kernel_traits<A>::Kernel Kernel;
186 return Kernel().do_intersect_3_object()(a, b);
187 }
188
189 template<typename A, typename B>
190 inline bool
do_intersect_impl(const A & a,const B & b,Dynamic_dimension_tag)191 do_intersect_impl(const A& a, const B& b, Dynamic_dimension_tag) {
192 typedef typename CGAL::Kernel_traits<A>::Kernel Kernel;
193 return Kernel().do_intersect_d_object()(a, b);
194 }
195
196 } // namespace internal
197 } // namespace Intersections
198
199 // See overloads in the respective header files
200
201 // template<typename A, typename B>
202 // inline
203 // typename Intersection_traits< typename Kernel_traits<A>::Kernel, A, B>::result_type >::type
204 // intersection(const A& a, const B& b) {
205 // CGAL_static_assertion_msg( (boost::is_same<typename A::Ambient_dimension, typename B::Ambient_dimension>::value),
206 // "intersection with objects of different dimensions not supported");
207 // return internal::intersection_impl(a, b, typename A::Ambient_dimension());
208 // }
209
210 // template<typename A, typename B>
211 // inline
212 // bool
213 // do_intersect(const A& a, const B& b) {
214 // CGAL_static_assertion_msg((boost::is_same<typename A::Ambient_dimension, typename B::Ambient_dimension>::value),
215 // "do_intersect with objects of different dimensions not supported");
216 // return internal::do_intersect_impl(a, b, typename A::Ambient_dimension());
217 // }
218
219 } // CGAL
220
221 #endif /* CGAL_INTERSECTION_TRAITS_H */
222