123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
- #define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
- #include <cstddef>
- #include <string>
- #include <boost/concept_check.hpp>
- #include <boost/geometry/arithmetic/determinant.hpp>
- #include <boost/geometry/strategies/side_info.hpp>
- #include <boost/geometry/util/math.hpp>
- #include <boost/geometry/util/select_calculation_type.hpp>
- #include <boost/geometry/util/select_most_precise.hpp>
- namespace boost { namespace geometry
- {
- namespace policies { namespace relate
- {
- struct direction_type
- {
-
- inline direction_type(side_info const& s, char h,
- int ha, int hb,
- int da = 0, int db = 0,
- bool op = false)
- : how(h)
- , opposite(op)
- , how_a(ha)
- , how_b(hb)
- , dir_a(da)
- , dir_b(db)
- , sides(s)
- {
- arrival[0] = ha;
- arrival[1] = hb;
- }
- inline direction_type(char h, bool op, int ha = 0, int hb = 0)
- : how(h)
- , opposite(op)
- , how_a(ha)
- , how_b(hb)
- , dir_a(0)
- , dir_b(0)
- {
- arrival[0] = ha;
- arrival[1] = hb;
- }
-
-
-
- char how;
-
- bool opposite;
-
-
-
- int how_a;
- int how_b;
-
-
-
-
-
-
- int dir_a;
- int dir_b;
-
- side_info sides;
-
- int arrival[2];
-
-
-
-
-
-
-
-
-
-
-
- };
- struct segments_direction
- {
- typedef direction_type return_type;
- template
- <
- typename Segment1,
- typename Segment2,
- typename SegmentIntersectionInfo
- >
- static inline return_type segments_crosses(side_info const& sides,
- SegmentIntersectionInfo const& ,
- Segment1 const& , Segment2 const& )
- {
- bool const ra0 = sides.get<0,0>() == 0;
- bool const ra1 = sides.get<0,1>() == 0;
- bool const rb0 = sides.get<1,0>() == 0;
- bool const rb1 = sides.get<1,1>() == 0;
- return
-
- ra0 && rb0 ? calculate_side<1>(sides, 'f', -1, -1)
-
- : ra1 && rb1 ? calculate_side<0>(sides, 't', 1, 1)
-
-
-
- : ra1 && rb0 ? angle<1>(sides, 'a', 1, -1)
-
-
- : ra0 && rb1 ? angle<0>(sides, 'a', -1, 1)
-
- : rb0 ? starts_from_middle(sides, 'B', 0, -1)
-
- : ra0 ? starts_from_middle(sides, 'A', -1, 0)
-
- : rb1 ? b_ends_at_middle(sides)
-
- : ra1 ? a_ends_at_middle(sides)
-
- : calculate_side<1>(sides, 'i', -1, -1)
- ;
- }
- template <typename Ratio>
- static inline int arrival_value(Ratio const& r_from, Ratio const& r_to)
- {
-
-
-
-
-
-
-
-
-
-
- return r_to.in_segment() ? 1
- : r_to.on_segment() ? 0
- : r_from.on_segment() ? -1
- : -1
- ;
- }
- template <typename Ratio>
- static inline void analyze(Ratio const& r,
- int& in_segment_count,
- int& on_end_count,
- int& outside_segment_count)
- {
- if (r.on_end())
- {
- on_end_count++;
- }
- else if (r.in_segment())
- {
- in_segment_count++;
- }
- else
- {
- outside_segment_count++;
- }
- }
- static inline int arrival_from_position_value(int , int v_to)
- {
- return v_to == 2 ? 1
- : v_to == 1 || v_to == 3 ? 0
-
- : -1;
-
-
- }
- static inline void analyse_position_value(int pos_val,
- int & in_segment_count,
- int & on_end_count,
- int & outside_segment_count)
- {
- if ( pos_val == 1 || pos_val == 3 )
- {
- on_end_count++;
- }
- else if ( pos_val == 2 )
- {
- in_segment_count++;
- }
- else
- {
- outside_segment_count++;
- }
- }
- template <typename Segment1, typename Segment2, typename Ratio>
- static inline return_type segments_collinear(
- Segment1 const& , Segment2 const& , bool opposite,
- int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,
- Ratio const& , Ratio const& ,
- Ratio const& , Ratio const& )
- {
- return_type r('c', opposite);
-
-
- r.arrival[0] = arrival_from_position_value(a1_wrt_b, a2_wrt_b);
- r.arrival[1] = arrival_from_position_value(b1_wrt_a, b2_wrt_a);
-
- int a_in_segment_count = 0;
- int a_on_end_count = 0;
- int a_outside_segment_count = 0;
- int b_in_segment_count = 0;
- int b_on_end_count = 0;
- int b_outside_segment_count = 0;
- analyse_position_value(a1_wrt_b,
- a_in_segment_count, a_on_end_count, a_outside_segment_count);
- analyse_position_value(a2_wrt_b,
- a_in_segment_count, a_on_end_count, a_outside_segment_count);
- analyse_position_value(b1_wrt_a,
- b_in_segment_count, b_on_end_count, b_outside_segment_count);
- analyse_position_value(b2_wrt_a,
- b_in_segment_count, b_on_end_count, b_outside_segment_count);
- if (a_on_end_count == 1
- && b_on_end_count == 1
- && a_outside_segment_count == 1
- && b_outside_segment_count == 1)
- {
-
-
-
-
-
- if (! opposite)
- {
- r.how = 'a';
- }
- else
- {
- r.how = r.arrival[0] == 0 ? 't' : 'f';
- }
- }
- else if (a_on_end_count == 2
- && b_on_end_count == 2)
- {
- r.how = 'e';
- }
- return r;
- }
- template <typename Segment>
- static inline return_type degenerate(Segment const& , bool)
- {
- return return_type('0', false);
- }
- template <typename Segment, typename Ratio>
- static inline return_type one_degenerate(Segment const& ,
- Ratio const& ,
- bool)
- {
-
- return return_type('0', false);
- }
- static inline return_type disjoint()
- {
- return return_type('d', false);
- }
- static inline return_type error(std::string const&)
- {
-
-
-
- return return_type('E', false);
- }
- private :
- template <std::size_t I>
- static inline return_type calculate_side(side_info const& sides,
- char how, int how_a, int how_b)
- {
- int const dir = sides.get<1, I>() == 1 ? 1 : -1;
- return return_type(sides, how, how_a, how_b, -dir, dir);
- }
- template <std::size_t I>
- static inline return_type angle(side_info const& sides,
- char how, int how_a, int how_b)
- {
- int const dir = sides.get<1, I>() == 1 ? 1 : -1;
- return return_type(sides, how, how_a, how_b, dir, dir);
- }
- static inline return_type starts_from_middle(side_info const& sides,
- char which,
- int how_a, int how_b)
- {
-
- int dir = sides.get<1, 1>() == 1 ? 1 : -1;
-
- bool const is_a = which == 'A';
- if (is_a)
- {
- dir = -dir;
- }
- return return_type(sides, 's',
- how_a,
- how_b,
- is_a ? dir : -dir,
- ! is_a ? dir : -dir);
- }
-
- static inline return_type a_ends_at_middle(side_info const& sides)
- {
-
-
- int const dir = sides.get<1, 1>() == 1 ? 1 : -1;
- return return_type(sides, 'm', 1, 0, dir, dir);
- }
- static inline return_type b_ends_at_middle(side_info const& sides)
- {
- int const dir = sides.get<0, 1>() == 1 ? 1 : -1;
- return return_type(sides, 'm', 0, 1, dir, dir);
- }
- };
- }}
- }}
- #endif
|