summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp')
-rw-r--r--boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
new file mode 100644
index 0000000000..395921ccaa
--- /dev/null
+++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
@@ -0,0 +1,191 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+
+// 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_BUFFER_GET_PIECE_TURNS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace buffer
+{
+
+
+struct piece_get_box
+{
+ template <typename Box, typename Piece>
+ static inline void apply(Box& total, Piece const& piece)
+ {
+ geometry::expand(total, piece.robust_envelope);
+ }
+};
+
+struct piece_ovelaps_box
+{
+ template <typename Box, typename Piece>
+ static inline bool apply(Box const& box, Piece const& piece)
+ {
+ return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope);
+ }
+};
+
+template
+<
+ typename Rings,
+ typename Turns,
+ typename RobustPolicy
+>
+class piece_turn_visitor
+{
+ Rings const& m_rings;
+ Turns& m_turns;
+ RobustPolicy const& m_robust_policy;
+
+ template <typename Piece>
+ inline bool is_adjacent(Piece const& piece1, Piece const& piece2) const
+ {
+ if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
+ {
+ return false;
+ }
+
+ return piece1.index == piece2.left_index
+ || piece1.index == piece2.right_index;
+ }
+
+ template <typename Range, typename Iterator>
+ inline void move_to_next_point(Range const& range, Iterator& next) const
+ {
+ ++next;
+ if (next == boost::end(range))
+ {
+ next = boost::begin(range) + 1;
+ }
+ }
+
+ template <typename Range, typename Iterator>
+ inline Iterator next_point(Range const& range, Iterator it) const
+ {
+ Iterator result = it;
+ move_to_next_point(range, result);
+ // TODO: we could use either piece-boundaries, or comparison with
+ // robust points, to check if the point equals the last one
+ while(geometry::equals(*it, *result))
+ {
+ move_to_next_point(range, result);
+ }
+ return result;
+ }
+
+ template <typename Piece>
+ inline void calculate_turns(Piece const& piece1, Piece const& piece2)
+ {
+ typedef typename boost::range_value<Rings const>::type ring_type;
+ typedef typename boost::range_value<Turns const>::type turn_type;
+ typedef typename boost::range_iterator<ring_type const>::type iterator;
+
+ segment_identifier seg_id1 = piece1.first_seg_id;
+ segment_identifier seg_id2 = piece2.first_seg_id;
+
+ if (seg_id1.segment_index < 0 || seg_id2.segment_index < 0)
+ {
+ return;
+ }
+
+ ring_type const& ring1 = m_rings[seg_id1.multi_index];
+ iterator it1_first = boost::begin(ring1) + seg_id1.segment_index;
+ iterator it1_last = boost::begin(ring1) + piece1.last_segment_index;
+
+ ring_type const& ring2 = m_rings[seg_id2.multi_index];
+ iterator it2_first = boost::begin(ring2) + seg_id2.segment_index;
+ iterator it2_last = boost::begin(ring2) + piece2.last_segment_index;
+
+ turn_type the_model;
+ the_model.operations[0].piece_index = piece1.index;
+ the_model.operations[0].seg_id = piece1.first_seg_id;
+
+ iterator it1 = it1_first;
+ for (iterator prev1 = it1++;
+ it1 != it1_last;
+ prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
+ {
+ the_model.operations[1].piece_index = piece2.index;
+ the_model.operations[1].seg_id = piece2.first_seg_id;
+
+ iterator next1 = next_point(ring1, it1);
+
+ iterator it2 = it2_first;
+ for (iterator prev2 = it2++;
+ it2 != it2_last;
+ prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
+ {
+ iterator next2 = next_point(ring2, it2);
+
+ // TODO: internally get_turn_info calculates robust points.
+ // But they are already calculated.
+ // We should be able to use them.
+ // this means passing them to this visitor,
+ // and iterating in sync with them...
+ typedef detail::overlay::get_turn_info
+ <
+ detail::overlay::assign_null_policy
+ > turn_policy;
+
+ turn_policy::apply(*prev1, *it1, *next1,
+ *prev2, *it2, *next2,
+ false, false, false, false,
+ the_model, m_robust_policy,
+ std::back_inserter(m_turns));
+ }
+ }
+ }
+
+public:
+
+ piece_turn_visitor(Rings const& ring_collection,
+ Turns& turns,
+ RobustPolicy const& robust_policy)
+ : m_rings(ring_collection)
+ , m_turns(turns)
+ , m_robust_policy(robust_policy)
+ {}
+
+ template <typename Piece>
+ inline void apply(Piece const& piece1, Piece const& piece2,
+ bool first = true)
+ {
+ boost::ignore_unused_variable_warning(first);
+ if ( is_adjacent(piece1, piece2)
+ || detail::disjoint::disjoint_box_box(piece1.robust_envelope,
+ piece2.robust_envelope))
+ {
+ return;
+ }
+ calculate_turns(piece1, piece2);
+ }
+};
+
+
+}} // namespace detail::buffer
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP