1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
10 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
12 #include <boost/range.hpp>
14 #include <boost/geometry/algorithms/equals.hpp>
15 #include <boost/geometry/algorithms/expand.hpp>
16 #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
17 #include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
18 #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
21 namespace boost { namespace geometry
25 #ifndef DOXYGEN_NO_DETAIL
26 namespace detail { namespace buffer
32 template <typename Box, typename Piece>
33 static inline void apply(Box& total, Piece const& piece)
35 geometry::expand(total, piece.robust_envelope);
39 struct piece_ovelaps_box
41 template <typename Box, typename Piece>
42 static inline bool apply(Box const& box, Piece const& piece)
44 return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope);
54 class piece_turn_visitor
58 RobustPolicy const& m_robust_policy;
60 template <typename Piece>
61 inline bool is_adjacent(Piece const& piece1, Piece const& piece2) const
63 if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
68 return piece1.index == piece2.left_index
69 || piece1.index == piece2.right_index;
72 template <typename Range, typename Iterator>
73 inline void move_to_next_point(Range const& range, Iterator& next) const
76 if (next == boost::end(range))
78 next = boost::begin(range) + 1;
82 template <typename Range, typename Iterator>
83 inline Iterator next_point(Range const& range, Iterator it) const
86 move_to_next_point(range, result);
87 // TODO: we could use either piece-boundaries, or comparison with
88 // robust points, to check if the point equals the last one
89 while(geometry::equals(*it, *result))
91 move_to_next_point(range, result);
96 template <typename Piece>
97 inline void calculate_turns(Piece const& piece1, Piece const& piece2)
99 typedef typename boost::range_value<Rings const>::type ring_type;
100 typedef typename boost::range_value<Turns const>::type turn_type;
101 typedef typename boost::range_iterator<ring_type const>::type iterator;
103 segment_identifier seg_id1 = piece1.first_seg_id;
104 segment_identifier seg_id2 = piece2.first_seg_id;
106 if (seg_id1.segment_index < 0 || seg_id2.segment_index < 0)
111 ring_type const& ring1 = m_rings[seg_id1.multi_index];
112 iterator it1_first = boost::begin(ring1) + seg_id1.segment_index;
113 iterator it1_last = boost::begin(ring1) + piece1.last_segment_index;
115 ring_type const& ring2 = m_rings[seg_id2.multi_index];
116 iterator it2_first = boost::begin(ring2) + seg_id2.segment_index;
117 iterator it2_last = boost::begin(ring2) + piece2.last_segment_index;
120 the_model.operations[0].piece_index = piece1.index;
121 the_model.operations[0].seg_id = piece1.first_seg_id;
123 iterator it1 = it1_first;
124 for (iterator prev1 = it1++;
126 prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
128 the_model.operations[1].piece_index = piece2.index;
129 the_model.operations[1].seg_id = piece2.first_seg_id;
131 iterator next1 = next_point(ring1, it1);
133 iterator it2 = it2_first;
134 for (iterator prev2 = it2++;
136 prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
138 iterator next2 = next_point(ring2, it2);
140 // TODO: internally get_turn_info calculates robust points.
141 // But they are already calculated.
142 // We should be able to use them.
143 // this means passing them to this visitor,
144 // and iterating in sync with them...
145 typedef detail::overlay::get_turn_info
147 detail::overlay::assign_null_policy
150 turn_policy::apply(*prev1, *it1, *next1,
151 *prev2, *it2, *next2,
152 false, false, false, false,
153 the_model, m_robust_policy,
154 std::back_inserter(m_turns));
161 piece_turn_visitor(Rings const& ring_collection,
163 RobustPolicy const& robust_policy)
164 : m_rings(ring_collection)
166 , m_robust_policy(robust_policy)
169 template <typename Piece>
170 inline void apply(Piece const& piece1, Piece const& piece2,
173 boost::ignore_unused_variable_warning(first);
174 if ( is_adjacent(piece1, piece2)
175 || detail::disjoint::disjoint_box_box(piece1.robust_envelope,
176 piece2.robust_envelope))
180 calculate_turns(piece1, piece2);
185 }} // namespace detail::buffer
186 #endif // DOXYGEN_NO_DETAIL
189 }} // namespace boost::geometry
191 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP