// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // This file was modified by Oracle on 2016-2020. // Modifications copyright (c) 2016-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP #define BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { template struct cross_product { // We define cross product only for 2d (see Wolfram) and 3d. // In Math, it is also well-defined for 7-dimension. // Generalisation of cross product to n-dimension is defined as // wedge product but it is not direct analogue to binary cross product. BOOST_GEOMETRY_STATIC_ASSERT_FALSE( "Not implemented for this Dimension.", std::integral_constant); }; template <> struct cross_product<2> { template static void apply(P1 const& p1, P2 const& p2, ResultP& result) { assert_dimension(); assert_dimension(); assert_dimension(); // For 2-dimensions, analog of the cross product U(x,y) and V(x,y) is // Ux * Vy - Uy * Vx // which is returned as 0-component (or X) of 2d vector, 1-component is undefined. set<0>(result, get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2)); } }; template <> struct cross_product<3> { template static void apply(P1 const& p1, P2 const& p2, ResultP& result) { assert_dimension(); assert_dimension(); assert_dimension(); set<0>(result, get<1>(p1) * get<2>(p2) - get<2>(p1) * get<1>(p2)); set<1>(result, get<2>(p1) * get<0>(p2) - get<0>(p1) * get<2>(p2)); set<2>(result, get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2)); } template static constexpr ResultP apply(P1 const& p1, P2 const& p2) { assert_dimension(); assert_dimension(); assert_dimension(); return traits::make::apply( get<1>(p1) * get<2>(p2) - get<2>(p1) * get<1>(p2), get<2>(p1) * get<0>(p2) - get<0>(p1) * get<2>(p2), get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2)); } }; } // namespace detail #endif // DOXYGEN_NO_DETAIL /*! \brief Computes the cross product of two vectors. \details All vectors should have the same dimension, 3 or 2. \ingroup arithmetic \param p1 first vector \param p2 second vector \return the cross product vector */ template < typename ResultP, typename P1, typename P2, std::enable_if_t < dimension::value != 3 || ! traits::make::is_specialized, int > = 0 > inline ResultP cross_product(P1 const& p1, P2 const& p2) { BOOST_CONCEPT_ASSERT( (concepts::Point) ); BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); ResultP result; detail::cross_product::value>::apply(p1, p2, result); return result; } template < typename ResultP, typename P1, typename P2, std::enable_if_t < dimension::value == 3 && traits::make::is_specialized, int > = 0 > // workaround for VS2015 #if !defined(_MSC_VER) || (_MSC_VER >= 1910) constexpr #endif inline ResultP cross_product(P1 const& p1, P2 const& p2) { BOOST_CONCEPT_ASSERT((concepts::Point)); BOOST_CONCEPT_ASSERT((concepts::ConstPoint)); BOOST_CONCEPT_ASSERT((concepts::ConstPoint)); return detail::cross_product<3>::apply(p1, p2); } /*! \brief Computes the cross product of two vectors. \details All vectors should have the same dimension, 3 or 2. \ingroup arithmetic \param p1 first vector \param p2 second vector \return the cross product vector \qbk{[heading Examples]} \qbk{[cross_product] [cross_product_output]} */ template < typename P, std::enable_if_t < dimension

::value != 3 || ! traits::make

::is_specialized, int > = 0 > inline P cross_product(P const& p1, P const& p2) { BOOST_CONCEPT_ASSERT((concepts::Point

)); BOOST_CONCEPT_ASSERT((concepts::ConstPoint

)); P result; detail::cross_product::value>::apply(p1, p2, result); return result; } template < typename P, std::enable_if_t < dimension

::value == 3 && traits::make

::is_specialized, int > = 0 > // workaround for VS2015 #if !defined(_MSC_VER) || (_MSC_VER >= 1910) constexpr #endif inline P cross_product(P const& p1, P const& p2) { BOOST_CONCEPT_ASSERT((concepts::Point

)); BOOST_CONCEPT_ASSERT((concepts::ConstPoint

)); return detail::cross_product<3>::apply

(p1, p2); } }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP