// Copyright (c) 2011 GeometryFactory (France). All rights reserved. // 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$ // SPDX-License-Identifier: LGPL-3.0+ // // // Author(s) : Philipp Möller #ifndef CGAL_INTERSECTION_TRAITS_H #define CGAL_INTERSECTION_TRAITS_H #include #include #include #include #include #include #include // The macro CGAL_INTERSECTION_VERSION controls which version of the // intersection is used. // Currently two values are supported: // - 1, which means intersections with CGAL::Object // - 2, which means intersections with Intersection_traits and the // corresponding APIs in other modules // The default value is 2. #if !defined(CGAL_INTERSECTION_VERSION) #define CGAL_INTERSECTION_VERSION 2 #endif #if CGAL_INTERSECTION_VERSION < 2 #define CGAL_INTERSECTION_TRAITS_2(A, B, R1, R2) #define CGAL_INTERSECTION_TRAITS_3(A, B, R1, R2, R3) #else #define CGAL_INTERSECTION_TRAITS_2(A, B, R1, R2) \ template \ struct Intersection_traits { \ typedef typename boost::variant \ variant_type; \ typedef typename boost::optional< variant_type > result_type; \ }; #define CGAL_INTERSECTION_TRAITS_3(A, B, R1, R2, R3) \ template \ struct Intersection_traits { \ typedef typename boost::variant variant_type; \ typedef typename boost::optional< variant_type > result_type; \ }; #endif #define CGAL_INTERSECTION_FUNCTION(A, B, DIM) \ template \ inline \ typename cpp11::result_of::type \ intersection(const A& a, const B& b) { \ return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ } \ template \ inline \ typename cpp11::result_of::type \ intersection(const B& a, const A& b) { \ return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ } #define CGAL_INTERSECTION_FUNCTION_SELF(A, DIM) \ template \ inline \ typename cpp11::result_of::type \ intersection(const A & a, const A & b) { \ return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ } #define CGAL_DO_INTERSECT_FUNCTION(A, B, DIM) \ template \ inline bool \ do_intersect(const A& a, const B& b) { \ return BOOST_PP_CAT(K().do_intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ } \ template \ inline bool \ do_intersect(const B& a, const A& b) { \ return BOOST_PP_CAT(K().do_intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ } #define CGAL_DO_INTERSECT_FUNCTION_SELF(A, DIM) \ template \ inline bool \ do_intersect(const A & a, const A & b) { \ return BOOST_PP_CAT(K().do_intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ } namespace CGAL { // only declarationn template struct Intersection_traits { // This defaults to Object, if we use VERSION < 2 and do nothing // otherwise. #if CGAL_INTERSECTION_VERSION < 2 typedef CGAL::Object result_type; #endif }; // Alias that gets the Kernel automatically and does some error checking. // Including corresponding specialization for Bbox, as it has no Kernel. template class IT : public Intersection_traits< typename Kernel_traits::Kernel, A, B > { typedef typename Kernel_traits::Kernel A_Kernel; typedef typename Kernel_traits::Kernel B_Kernel; // CGAL_static_assertion_msg( (boost::is_same< A_Kernel, B_Kernel>::value), // "IT instantiated with objects from two different Kernels"); }; class Bbox_2; class Bbox_3; template class IT : public Intersection_traits< typename Kernel_traits::Kernel, CGAL::Bbox_2, B > { }; template class IT : public Intersection_traits< typename Kernel_traits::Kernel, CGAL::Bbox_3, B > { }; namespace internal { // this function is used to call either make_object or a // Intersection_traits::result_type constructor to create return // values. The Object version takes some dummy template arguments // that are needed for the return of the Intersection_traits. In // theory a one parameter variant could be returned, but this // _could_ come with conversion overhead and so we rather go for // the real type. // Overloads for empty returns are also provided. #if CGAL_INTERSECTION_VERSION < 2 #if defined(CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE) template inline CGAL::Object intersection_return(const T& t) { return CGAL::make_object(t); } #else template inline CGAL::Object intersection_return(T&& t) { return CGAL::make_object(std::forward(t)); } #endif // CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE template inline CGAL::Object intersection_return() { return CGAL::Object(); } #else #if defined(CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE) template inline typename cpp11::result_of::type intersection_return(const T& t) { return typename cpp11::result_of::type(t); } #else template inline typename cpp11::result_of::type intersection_return(T&& t) { return typename cpp11::result_of::type(std::forward(t)); } #endif // CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE template inline typename cpp11::result_of::type intersection_return() { return typename cpp11::result_of::type(); } #endif // CGAL_INTERSECTION_VERSION < 2 // Something similar to wrap around boost::get and object_cast to // prevent ifdefing too much. Another way could be to introduce an // overload of boost::get for Object. We only provide the pointer // casts here. But use references to const as parameters. This makes // it somewhat nicer. template inline const T* intersect_get(const CGAL::Object& o) { return CGAL::object_cast(&o); } template inline const T* intersect_get(const boost::optional< boost::variant >& v) { return boost::get(&*v); } template inline const T* intersect_get(const boost::variant & v) { return boost::get(&v); } template typename cpp11::result_of::Kernel::Intersect_2(A, B)>::type intersection_impl(const A& a, const B& b, CGAL::Dimension_tag<2>) { typedef typename CGAL::Kernel_traits::Kernel Kernel; return Kernel().intersect_2_object()(a, b); } template typename cpp11::result_of::Kernel::Intersect_3(A, B)>::type intersection_impl(const A& a, const B& b, Dimension_tag<3>) { typedef typename CGAL::Kernel_traits::Kernel Kernel; return Kernel().intersect_3_object()(a, b); } template typename Intersection_traits< typename CGAL::Kernel_traits::Kernel, A, B>::result_type intersection_impl(const A& a, const B& b, Dynamic_dimension_tag) { typedef typename CGAL::Kernel_traits::Kernel Kernel; return Kernel().intersect_d_object()(a, b); } template inline bool do_intersect_impl(const A& a, const B& b, CGAL::Dimension_tag<2>) { typedef typename CGAL::Kernel_traits::Kernel Kernel; return Kernel().do_intersect_2_object()(a, b); } template inline bool do_intersect_impl(const A& a, const B& b, Dimension_tag<3>) { typedef typename CGAL::Kernel_traits::Kernel Kernel; return Kernel().do_intersect_3_object()(a, b); } template inline bool do_intersect_impl(const A& a, const B& b, Dynamic_dimension_tag) { typedef typename CGAL::Kernel_traits::Kernel Kernel; return Kernel().do_intersect_d_object()(a, b); } } // internal // See overloads in the respective header files // template // inline // typename Intersection_traits< typename Kernel_traits::Kernel, A, B>::result_type >::type // intersection(const A& a, const B& b) { // CGAL_static_assertion_msg( (boost::is_same::value), // "intersection with objects of different dimensions not supported"); // return internal::intersection_impl(a, b, typename A::Ambient_dimension()); // } // template // inline // bool // do_intersect(const A& a, const B& b) { // CGAL_static_assertion_msg((boost::is_same::value), // "do_intersect with objects of different dimensions not supported"); // return internal::do_intersect_impl(a, b, typename A::Ambient_dimension()); // } } // CGAL #endif /* CGAL_INTERSECTION_TRAITS_H */