// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // This file was modified by Oracle on 2013, 2014, 2015, 2017. // Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, 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_ALGORITHMS_DETAIL_RELATE_TURNS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace relate { namespace turns { template struct assign_policy : overlay::assign_null_policy { static bool const include_degenerate = IncludeDegenerate; }; // GET_TURNS template < typename Geometry1, typename Geometry2, typename GetTurnPolicy = detail::get_turns::get_turn_info_type < Geometry1, Geometry2, assign_policy<> >, typename RobustPolicy = detail::no_rescale_policy > struct get_turns { typedef typename geometry::point_type::type point1_type; typedef overlay::turn_info < point1_type, typename segment_ratio_type::type, typename detail::get_turns::turn_operation_type < Geometry1, Geometry2, typename segment_ratio_type < point1_type, RobustPolicy >::type >::type > turn_info; template static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2) { detail::get_turns::no_interrupt_policy interrupt_policy; typename strategy::intersection::services::default_strategy < typename cs_tag::type >::type intersection_strategy; apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); } template static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, InterruptPolicy & interrupt_policy, IntersectionStrategy const& intersection_strategy) { RobustPolicy robust_policy = geometry::get_rescale_policy < RobustPolicy >(geometry1, geometry2); apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy); } template static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, InterruptPolicy & interrupt_policy, IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy) { static const bool reverse1 = detail::overlay::do_reverse < geometry::point_order::value >::value; static const bool reverse2 = detail::overlay::do_reverse < geometry::point_order::value >::value; dispatch::get_turns < typename geometry::tag::type, typename geometry::tag::type, Geometry1, Geometry2, reverse1, reverse2, GetTurnPolicy >::apply(0, geometry1, 1, geometry2, intersection_strategy, robust_policy, turns, interrupt_policy); } }; // TURNS SORTING AND SEARCHING template struct op_to_int { template inline int operator()(Operation const& op) const { switch(op.operation) { case detail::overlay::operation_none : return N; case detail::overlay::operation_union : return U; case detail::overlay::operation_intersection : return I; case detail::overlay::operation_blocked : return B; case detail::overlay::operation_continue : return C; case detail::overlay::operation_opposite : return O; } return -1; } }; template struct less_op_xxx_linear { template inline bool operator()(Turn const& left, Turn const& right) const { static OpToInt op_to_int; return op_to_int(left.operations[OpId]) < op_to_int(right.operations[OpId]); } }; template struct less_op_linear_linear : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> > {}; template struct less_op_linear_areal_single { template inline bool operator()(Turn const& left, Turn const& right) const { static const std::size_t other_op_id = (OpId + 1) % 2; static turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic; static turns::op_to_int<0,3,2,1,4,0> op_to_int_xiuc; segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id; segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id; typedef typename Turn::turn_operation_type operation_type; operation_type const& left_operation = left.operations[OpId]; operation_type const& right_operation = right.operations[OpId]; if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index ) { return op_to_int_xuic(left_operation) < op_to_int_xuic(right_operation); } else { return op_to_int_xiuc(left_operation) < op_to_int_xiuc(right_operation); } } }; template struct less_op_areal_linear : less_op_xxx_linear< OpId, op_to_int<0,1,0,0,2,0> > {}; template struct less_op_areal_areal { template inline bool operator()(Turn const& left, Turn const& right) const { static const std::size_t other_op_id = (OpId + 1) % 2; static op_to_int<0, 1, 2, 3, 4, 0> op_to_int_uixc; static op_to_int<0, 2, 1, 3, 4, 0> op_to_int_iuxc; segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id; segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id; typedef typename Turn::turn_operation_type operation_type; operation_type const& left_operation = left.operations[OpId]; operation_type const& right_operation = right.operations[OpId]; if ( left_other_seg_id.multi_index == right_other_seg_id.multi_index ) { if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index ) { return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation); } else { if ( left_other_seg_id.ring_index == -1 ) { if ( left_operation.operation == overlay::operation_union ) return false; else if ( left_operation.operation == overlay::operation_intersection ) return true; } else if ( right_other_seg_id.ring_index == -1 ) { if ( right_operation.operation == overlay::operation_union ) return true; else if ( right_operation.operation == overlay::operation_intersection ) return false; } return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation); } } else { return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation); } } }; template struct less_other_multi_index { static const std::size_t other_op_id = (OpId + 1) % 2; template inline bool operator()(Turn const& left, Turn const& right) const { return left.operations[other_op_id].seg_id.multi_index < right.operations[other_op_id].seg_id.multi_index; } }; // sort turns by G1 - source_index == 0 by: // seg_id -> distance -> operation template > > struct less { BOOST_STATIC_ASSERT(OpId < 2); template static inline bool use_fraction(Turn const& left, Turn const& right) { static LessOp less_op; return geometry::math::equals(left.operations[OpId].fraction, right.operations[OpId].fraction) ? less_op(left, right) : (left.operations[OpId].fraction < right.operations[OpId].fraction) ; } template inline bool operator()(Turn const& left, Turn const& right) const { segment_identifier const& sl = left.operations[OpId].seg_id; segment_identifier const& sr = right.operations[OpId].seg_id; return sl < sr || ( sl == sr && use_fraction(left, right) ); } }; }}} // namespace detail::relate::turns #endif // DOXYGEN_NO_DETAIL }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP