// Copyright (c) 2001-2004 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Sylvain Pion // Menelaos Karavelas #ifndef CGAL_CARTESIAN_CONVERTER_H #define CGAL_CARTESIAN_CONVERTER_H // This file contains the definition of a kernel converter, based on Cartesian // representation. It should work between *Cartesian and *Cartesian, // provided you give a NT converter from A to B. // There's a Homogeneous counterpart. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { // Guess which compiler needs this work around ? // ... VC++, again! namespace internal { template < typename K1, typename K2 > struct Default_converter { typedef typename K1::FT FT1; typedef typename K2::FT FT2; typedef ::CGAL::NT_converter Type; }; // Out will be a variant, source kernel and target kernel template struct Converting_visitor{ Converting_visitor(const Converter& conv, Output& out) : conv(&conv), out(&out) {} const Converter* conv; Output* out; template void operator()(const T& t) { *out = conv->operator()(t); } template void operator()(const std::vector& t) { typedef typename Type_mapper< T, typename Converter::Source_kernel, typename Converter::Target_kernel >::type value_type; std::vector< value_type > tmp; tmp.reserve(t.size()); for(typename std::vector< T >::const_iterator it = t.begin(); it != t.end(); ++it) { tmp.push_back(conv->operator()(*it)); } *out = tmp; } }; } // namespace internal template < class K1, class K2, class Converter /*= typename internal::Default_converter::Type*/> class Cartesian_converter : public Enum_converter { typedef Enum_converter Base; typedef Cartesian_converter Self; public: typedef K1 Source_kernel; typedef K2 Target_kernel; typedef Converter Number_type_converter; using Base::operator(); Origin operator()(Origin o) const { return o; } Null_vector operator()(Null_vector n) const { return n; } Return_base_tag operator()(Return_base_tag o) const { return o; } const Bbox_2& operator()(const Bbox_2& b) const { return b; } const Bbox_3& operator()(const Bbox_3& b) const { return b; } typename K2::FT operator()(const typename K1::FT& a) const { return conv(a); } template T operator()(const T t, std::enable_if_t::value>* = nullptr) const { return t; } // drop the boost::detail::variant::void_ generated by the macros // from the sequence, transform with the type mapper and throw the // new list into a variant // visit to get the type, and copy construct inside the return type template typename Type_mapper< std::optional< std::variant< U ... > >, K1, K2 >::type operator()(const std::optional< std::variant< U ... > >& o) const { typedef typename Type_mapper< std::optional< std::variant< U ... > >, K1, K2 >::type result_type; result_type res; if(!o) { // empty converts to empty return res; } internal::Converting_visitor conv_visitor = internal::Converting_visitor(*this, res); std::visit(conv_visitor, *o); return res; } template typename Type_mapper< std::variant< U ... >, K1, K2 >::type operator()(const std::variant< U ... > & o) const { typedef typename Type_mapper< std::variant< U ... >, K1, K2 >::type result_type; result_type res; internal::Converting_visitor conv_visitor = internal::Converting_visitor(*this, res); std::visit(conv_visitor, o); return res; } BOOST_MPL_HAS_XXX_TRAIT_DEF(Object_2); template ::value && has_Object_2::value, int> = 0> typename U2::Object_2 operator()(const typename U1::Object_2 &obj) const { #define CGAL_Kernel_obj(X) \ if (const typename K1::X * ptr = object_cast(&obj)) \ return make_object(operator()(*ptr)); #include #define CGAL_Kernel_obj(X) \ if (const std::vector * ptr = object_cast >(&obj)) { \ std::vector res; \ res.reserve((*ptr).size()); \ for(unsigned int i=0; i < (*ptr).size(); i++){ \ res.push_back(operator()((*ptr)[i])); \ } \ return make_object(res); \ } CGAL_Kernel_obj(Point_2) CGAL_Kernel_obj(Point_3) #undef CGAL_Kernel_obj CGAL_error_msg("Cartesian_converter is unable to determine what is wrapped in the Object"); return Object(); } std::vector operator()(const std::vector& v) const { std::vector res; res.reserve(v.size()); for(unsigned int i = 0; i < v.size(); i++) { res.push_back(operator()(v[i])); } return res; } // For SFINAE #define CGAL_Kernel_obj(X) \ BOOST_MPL_HAS_XXX_TRAIT_DEF(X); #include #undef CGAL_Kernel_obj template ::value && has_Point_2::value, int> = 0> typename U2::Point_2 operator()(const typename U1::Point_2& p) const { return k2.construct_point_2_object()(conv(k1.compute_x_2_object()(p)), conv(k1.compute_y_2_object()(p))); } template ::value && has_Weighted_point_2::value, int> = 0> typename U2::Weighted_point_2 operator()(const typename U1::Weighted_point_2& wp) const { return k2.construct_weighted_point_2_object()(operator()(k1.construct_point_2_object()(wp)), conv(k1.compute_weight_2_object()(wp))); } template ::value && has_Vector_2::value, int> = 0> typename U2::Vector_2 operator()(const typename U1::Vector_2& v) const { return k2.construct_vector_2_object()(conv(k1.compute_x_2_object()(v)), conv(k1.compute_y_2_object()(v))); } template ::value && has_Direction_2::value, int> = 0> typename U2::Direction_2 operator()(const typename U1::Direction_2& d) const { return k2.construct_direction_2_object()(conv(k1.compute_dx_2_object()(d)), conv(k1.compute_dy_2_object()(d))); } template ::value && has_Segment_2::value, int> = 0> typename U2::Segment_2 operator()(const typename U1::Segment_2& s) const { return k2.construct_segment_2_object()(operator()(k1.construct_source_2_object()(s)), operator()(k1.construct_target_2_object()(s))); } template ::value && has_Line_2::value, int> = 0> typename U2::Line_2 operator()(const typename U1::Line_2& l) const { return k2.construct_line_2_object()(conv(k1.compute_a_2_object()(l)), conv(k1.compute_b_2_object()(l)), conv(k1.compute_c_2_object()(l))); } template ::value && has_Ray_2::value, int> = 0> typename U2::Ray_2 operator()(const typename U1::Ray_2& r) const { return k2.construct_ray_2_object()(operator()(k1.construct_source_2_object()(r)), operator()(k1.construct_second_point_2_object()(r))); } template ::value && has_Circle_2::value, int> = 0> typename U2::Circle_2 operator()(const typename U1::Circle_2& c) const { return k2.construct_circle_2_object()(operator()(k1.construct_center_2_object()(c)), conv(k1.compute_squared_radius_2_object()(c)), k1.orientation_2_object()(c)); } template ::value && has_Triangle_2::value, int> = 0> typename U2::Triangle_2 operator()(const typename U1::Triangle_2& tr) const { return k2.construct_triangle_2_object()(operator()(k1.construct_vertex_2_object()(tr,0)), operator()(k1.construct_vertex_2_object()(tr,1)), operator()(k1.construct_vertex_2_object()(tr,2)) ); } template ::value && has_Iso_rectangle_2::value, int> = 0> typename U2::Iso_rectangle_2 operator()(const typename U1::Iso_rectangle_2& ir) const { return k2.construct_iso_rectangle_2_object()(operator()(k1.construct_min_vertex_2_object()(ir)), operator()(k1.construct_max_vertex_2_object()(ir)), 0); } template ::value && has_Point_3::value, int> = 0> typename U2::Point_3 operator()(const typename U1::Point_3& p) const { return k2.construct_point_3_object()(conv(k1.compute_x_3_object()(p)), conv(k1.compute_y_3_object()(p)), conv(k1.compute_z_3_object()(p))); } template ::value && has_Weighted_point_3::value, int> = 0> typename U2::Weighted_point_3 operator()(const typename U1::Weighted_point_3& wp) const { return k2.construct_weighted_point_3_object()(operator()(k1.construct_point_3_object()(wp)), conv(k1.compute_weight_3_object()(wp))); } template ::value && has_Vector_3::value, int> = 0> typename U2::Vector_3 operator()(const typename U1::Vector_3& v) const { return k2.construct_vector_3_object()(conv(k1.compute_x_3_object()(v)), conv(k1.compute_y_3_object()(v)), conv(k1.compute_z_3_object()(v))); } template ::value && has_Direction_3::value, int> = 0> typename U2::Direction_3 operator()(const typename U1::Direction_3& d) const { return k2.construct_direction_3_object()(conv(k1.compute_dx_3_object()(d)), conv(k1.compute_dy_3_object()(d)), conv(k1.compute_dz_3_object()(d))); } template ::value && has_Segment_3::value, int> = 0> typename U2::Segment_3 operator()(const typename U1::Segment_3& s) const { return k2.construct_segment_3_object()(operator()(k1.construct_source_3_object()(s)), operator()(k1.construct_target_3_object()(s))); } template ::value && has_Line_3::value, int> = 0> typename U2::Line_3 operator()(const typename U1::Line_3& l) const { return k2.construct_line_3_object()(operator()(k1.construct_point_on_3_object()(l)), operator()(k1.construct_vector_3_object()(l))); } template ::value && has_Ray_3::value, int> = 0> typename U2::Ray_3 operator()(const typename U1::Ray_3& r) const { return k2.construct_ray_3_object()(operator()(k1.construct_source_3_object()(r)), operator()(k1.construct_second_point_3_object()(r))); } template ::value && has_Sphere_3::value, int> = 0> typename U2::Sphere_3 operator()(const typename U1::Sphere_3& s) const { return k2.construct_sphere_3_object()(operator()(k1.construct_center_3_object()(s)), conv(k1.compute_squared_radius_3_object()(s)), k1.orientation_3_object()(s)); } template ::value && has_Circle_3::value, int> = 0> typename U2::Circle_3 operator()(const typename U1::Circle_3& c) const { return k2.construct_circle_3_object()(operator()(k1.construct_sphere_3_object()(c)), operator()(k1.construct_plane_3_object()(c)), 1); } template ::value && has_Triangle_3::value, int> = 0> typename U2::Triangle_3 operator()(const typename U1::Triangle_3& tr) const { return k2.construct_triangle_3_object()(operator()(k1.construct_vertex_3_object()(tr,0)), operator()(k1.construct_vertex_3_object()(tr,1)), operator()(k1.construct_vertex_3_object()(tr,2))); } template ::value && has_Tetrahedron_3::value, int> = 0> typename U2::Tetrahedron_3 operator()(const typename U1::Tetrahedron_3& tet) const { return k2.construct_tetrahedron_3_object()(operator()(k1.construct_vertex_3_object()(tet,0)), operator()(k1.construct_vertex_3_object()(tet,1)), operator()(k1.construct_vertex_3_object()(tet,2)), operator()(k1.construct_vertex_3_object()(tet,3))); } template ::value && has_Plane_3::value, int> = 0> typename U2::Plane_3 operator()(const typename U1::Plane_3& pl) const { return k2.construct_plane_3_object()(conv(k1.compute_a_3_object()(pl)), conv(k1.compute_b_3_object()(pl)), conv(k1.compute_c_3_object()(pl)), conv(k1.compute_d_3_object()(pl))); } template ::value && has_Iso_cuboid_3::value, int> = 0> typename U2::Iso_cuboid_3 operator()(const typename U1::Iso_cuboid_3& ic) const { return k2.construct_iso_cuboid_3_object()(operator()(k1.construct_min_vertex_3_object()(ic)), operator()(k1.construct_max_vertex_3_object()(ic)), 0); } template ::value && has_Point_2::value, int> = 0> std::pair operator()(const std::pair& pp) const { return std::make_pair(operator()(pp.first), operator()(pp.second)); } BOOST_MPL_HAS_XXX_TRAIT_DEF(Aff_transformation_2); BOOST_MPL_HAS_XXX_TRAIT_DEF(Aff_transformation_3); template ::value && has_Aff_transformation_2::value, int> = 0> typename U2::Aff_transformation_2 operator()(const typename U1::Aff_transformation_2& a) const { return { conv(a.m(0,0)), conv(a.m(0,1)), conv(a.m(0,2)), conv(a.m(1,0)), conv(a.m(1,1)), conv(a.m(1,2)), conv(a.m(2,2)) }; } template ::value && has_Aff_transformation_3::value, int> = 0> typename U2::Aff_transformation_3 operator()(const typename U1::Aff_transformation_3& a) const { return { conv(a.m(0,0)), conv(a.m(0,1)), conv(a.m(0,2)), conv(a.m(0,3)), conv(a.m(1,0)), conv(a.m(1,1)), conv(a.m(1,2)), conv(a.m(1,3)), conv(a.m(2,0)), conv(a.m(2,1)), conv(a.m(2,2)), conv(a.m(2,3)), conv(a.m(3,3)) }; } private: Converter conv; K1 k1; K2 k2; }; // Specialization when converting to the same kernel, // to avoid making copies. template < class K, class C > class Cartesian_converter { public: typedef K Source_kernel; typedef K Target_kernel; typedef C Number_type_converter; template < typename T > const T& operator()(const T& t) const { return t; } }; } //namespace CGAL #endif // CGAL_CARTESIAN_CONVERTER_H