summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp')
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp192
1 files changed, 143 insertions, 49 deletions
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index a501e3f197..545d89cb9b 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -16,11 +16,14 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/is_convex.hpp>
#include <boost/geometry/strategies/buffer.hpp>
@@ -126,6 +129,11 @@ struct buffered_piece_collection
typedef geometry::model::ring<robust_point_type> robust_ring_type;
typedef geometry::model::box<robust_point_type> robust_box_type;
+ typedef typename default_comparable_distance_result
+ <
+ robust_point_type
+ >::type robust_comparable_radius_type;
+
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<point_type>::type
@@ -159,7 +167,7 @@ struct buffered_piece_collection
struct robust_turn
{
- int turn_index;
+ std::size_t turn_index;
int operation_index;
robust_point_type point;
segment_identifier seg_id;
@@ -172,10 +180,10 @@ struct buffered_piece_collection
typedef geometry::section<robust_box_type, 1> section_type;
strategy::buffer::piece_type type;
- int index;
+ signed_size_type index;
- int left_index; // points to previous piece of same ring
- int right_index; // points to next piece of same ring
+ signed_size_type left_index; // points to previous piece of same ring
+ signed_size_type right_index; // points to next piece of same ring
// The next two members (1, 2) form together a complete clockwise ring
// for each piece (with one dupped point)
@@ -183,21 +191,21 @@ struct buffered_piece_collection
// 1: half, part of offsetted_rings
segment_identifier first_seg_id;
- int last_segment_index; // no segment-identifier - it is the same as first_seg_id
- int offsetted_count; // part in robust_ring which is part of offsetted ring
+ signed_size_type last_segment_index; // no segment-identifier - it is the same as first_seg_id
+ signed_size_type offsetted_count; // part in robust_ring which is part of offsetted ring
#if defined(BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS)
// 2: half, not part of offsetted rings - part of robust ring
std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
#endif
+ bool is_convex;
bool is_monotonic_increasing[2]; // 0=x, 1=y
bool is_monotonic_decreasing[2]; // 0=x, 1=y
// Monotonic sections of pieces around points
std::vector<section_type> sections;
-
// Robust representations
// 3: complete ring
robust_ring_type robust_ring;
@@ -206,6 +214,27 @@ struct buffered_piece_collection
robust_box_type robust_offsetted_envelope;
std::vector<robust_turn> robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead
+
+ robust_point_type robust_center;
+ robust_comparable_radius_type robust_min_comparable_radius;
+ robust_comparable_radius_type robust_max_comparable_radius;
+
+ piece()
+ : type(strategy::buffer::piece_type_unknown)
+ , index(-1)
+ , left_index(-1)
+ , right_index(-1)
+ , last_segment_index(-1)
+ , offsetted_count(-1)
+ , is_convex(false)
+ , robust_min_comparable_radius(0)
+ , robust_max_comparable_radius(0)
+ {
+ is_monotonic_increasing[0] = false;
+ is_monotonic_increasing[1] = false;
+ is_monotonic_decreasing[0] = false;
+ is_monotonic_decreasing[1] = false;
+ }
};
struct robust_original
@@ -244,7 +273,7 @@ struct buffered_piece_collection
piece_vector_type m_pieces;
turn_vector_type m_turns;
- int m_first_piece_index;
+ signed_size_type m_first_piece_index;
buffered_ring_collection<buffered_ring<Ring> > offsetted_rings; // indexed by multi_index
std::vector<robust_original> robust_originals; // robust representation of the original(s)
@@ -444,6 +473,7 @@ struct buffered_piece_collection
{
it->location = inside_buffer;
}
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
if (it->count_within_near_offsetted > 0)
{
// Within can have in rare cases a rounding issue. We don't discard this
@@ -451,6 +481,7 @@ struct buffered_piece_collection
// will never start a new ring from this type of points.
it->selectable_start = false;
}
+#endif
}
}
@@ -515,7 +546,7 @@ struct buffered_piece_collection
{
// Add rescaled turn points to corresponding pieces
// (after this, each turn occurs twice)
- int index = 0;
+ std::size_t index = 0;
for (typename boost::range_iterator<turn_vector_type>::type it =
boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index)
{
@@ -544,16 +575,16 @@ struct buffered_piece_collection
}
}
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
// Insert all rescaled turn-points into these rings, to form a
// reliable integer-based ring. All turns can be compared (inside) to this
// rings to see if they are inside.
- for (typename piece_vector_type::iterator it = boost::begin(m_pieces);
- it != boost::end(m_pieces);
- ++it)
+ for (typename boost::range_iterator<piece_vector_type>::type
+ it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it)
{
piece& pc = *it;
- int piece_segment_index = pc.first_seg_id.segment_index;
+ signed_size_type piece_segment_index = pc.first_seg_id.segment_index;
if (! pc.robust_turns.empty())
{
if (pc.robust_turns.size() > 1u)
@@ -561,14 +592,14 @@ struct buffered_piece_collection
std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less());
}
// Walk through them, in reverse to insert at right index
- int index_offset = pc.robust_turns.size() - 1;
- for (typename std::vector<robust_turn>::const_reverse_iterator
- rit = pc.robust_turns.rbegin();
- rit != pc.robust_turns.rend();
+ signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1;
+ for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type
+ rit = boost::const_rbegin(pc.robust_turns);
+ rit != boost::const_rend(pc.robust_turns);
++rit, --index_offset)
{
- int const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
- BOOST_ASSERT
+ signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
+ BOOST_GEOMETRY_ASSERT
(
index_in_vector > 0
&& index_in_vector < pc.offsetted_count
@@ -582,7 +613,8 @@ struct buffered_piece_collection
}
}
- BOOST_ASSERT(assert_indices_in_robust_rings());
+ BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings());
+#endif
}
template <std::size_t Dimension>
@@ -607,6 +639,8 @@ struct buffered_piece_collection
pc.is_monotonic_decreasing[0] = true;
pc.is_monotonic_decreasing[1] = true;
+ pc.is_convex = geometry::is_convex(pc.robust_ring);
+
if (pc.offsetted_count < 2)
{
return;
@@ -615,14 +649,13 @@ struct buffered_piece_collection
typename robust_ring_type::const_iterator current = pc.robust_ring.begin();
typename robust_ring_type::const_iterator next = current + 1;
- for (int i = 1; i < pc.offsetted_count; i++)
+ for (signed_size_type i = 1; i < pc.offsetted_count; i++)
{
determine_monotonicity<0>(pc, *current, *next);
determine_monotonicity<1>(pc, *current, *next);
current = next;
++next;
}
-
}
void determine_properties()
@@ -659,7 +692,31 @@ struct buffered_piece_collection
geometry::sectionalize<false, dimensions>(pc.robust_ring,
detail::no_rescale_policy(), pc.sections);
- // TODO (next phase) determine min/max radius
+ // Determine min/max radius
+ typedef geometry::model::referring_segment<robust_point_type const>
+ robust_segment_type;
+
+ typename robust_ring_type::const_iterator current = pc.robust_ring.begin();
+ typename robust_ring_type::const_iterator next = current + 1;
+
+ for (signed_size_type i = 1; i < pc.offsetted_count; i++)
+ {
+ robust_segment_type s(*current, *next);
+ robust_comparable_radius_type const d
+ = geometry::comparable_distance(pc.robust_center, s);
+
+ if (i == 1 || d < pc.robust_min_comparable_radius)
+ {
+ pc.robust_min_comparable_radius = d;
+ }
+ if (i == 1 || d > pc.robust_max_comparable_radius)
+ {
+ pc.robust_max_comparable_radius = d;
+ }
+
+ current = next;
+ ++next;
+ }
}
inline void prepare_buffered_point_pieces()
@@ -730,7 +787,7 @@ struct buffered_piece_collection
inline void start_new_ring()
{
- int const n = offsetted_rings.size();
+ signed_size_type const n = static_cast<signed_size_type>(offsetted_rings.size());
current_segment_id.source_index = 0;
current_segment_id.multi_index = n;
current_segment_id.ring_index = -1;
@@ -739,12 +796,35 @@ struct buffered_piece_collection
offsetted_rings.resize(n + 1);
current_robust_ring.clear();
- m_first_piece_index = boost::size(m_pieces);
+ m_first_piece_index = static_cast<signed_size_type>(boost::size(m_pieces));
+ }
+
+ inline void abort_ring()
+ {
+ // Remove all created pieces for this ring, sections, last offsetted
+ while (! m_pieces.empty()
+ && m_pieces.back().first_seg_id.multi_index
+ == current_segment_id.multi_index)
+ {
+ m_pieces.erase(m_pieces.end() - 1);
+ }
+
+ while (! monotonic_sections.empty()
+ && monotonic_sections.back().ring_id.multi_index
+ == current_segment_id.multi_index)
+ {
+ monotonic_sections.erase(monotonic_sections.end() - 1);
+ }
+
+ offsetted_rings.erase(offsetted_rings.end() - 1);
+ current_robust_ring.clear();
+
+ m_first_piece_index = -1;
}
inline void update_closing_point()
{
- BOOST_ASSERT(! offsetted_rings.empty());
+ BOOST_GEOMETRY_ASSERT(! offsetted_rings.empty());
buffered_ring<Ring>& added = offsetted_rings.back();
if (! boost::empty(added))
{
@@ -764,7 +844,7 @@ struct buffered_piece_collection
// For now, it is made equal because due to numerical instability,
// it can be a tiny bit off, possibly causing a self-intersection
- BOOST_ASSERT(boost::size(m_pieces) > 0);
+ BOOST_GEOMETRY_ASSERT(boost::size(m_pieces) > 0);
if (! ring.empty()
&& current_segment_id.segment_index
== m_pieces.back().first_seg_id.segment_index)
@@ -773,6 +853,13 @@ struct buffered_piece_collection
}
}
+ inline void set_piece_center(point_type const& center)
+ {
+ BOOST_GEOMETRY_ASSERT(! m_pieces.empty());
+ geometry::recalculate(m_pieces.back().robust_center, center,
+ m_robust_policy);
+ }
+
inline void finish_ring(bool is_interior = false, bool has_interiors = false)
{
if (m_first_piece_index == -1)
@@ -780,12 +867,12 @@ struct buffered_piece_collection
return;
}
- if (m_first_piece_index < static_cast<int>(boost::size(m_pieces)))
+ if (m_first_piece_index < static_cast<signed_size_type>(boost::size(m_pieces)))
{
// If piece was added
// Reassign left-of-first and right-of-last
geometry::range::at(m_pieces, m_first_piece_index).left_index
- = boost::size(m_pieces) - 1;
+ = static_cast<signed_size_type>(boost::size(m_pieces)) - 1;
geometry::range::back(m_pieces).right_index = m_first_piece_index;
}
m_first_piece_index = -1;
@@ -794,7 +881,7 @@ struct buffered_piece_collection
if (! current_robust_ring.empty())
{
- BOOST_ASSERT
+ BOOST_GEOMETRY_ASSERT
(
geometry::equals(current_robust_ring.front(),
current_robust_ring.back())
@@ -808,20 +895,20 @@ struct buffered_piece_collection
inline void set_current_ring_concave()
{
- BOOST_ASSERT(boost::size(offsetted_rings) > 0);
+ BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0);
offsetted_rings.back().has_concave = true;
}
- inline int add_point(point_type const& p)
+ inline signed_size_type add_point(point_type const& p)
{
- BOOST_ASSERT(boost::size(offsetted_rings) > 0);
+ BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0);
buffered_ring<Ring>& current_ring = offsetted_rings.back();
update_last_point(p, current_ring);
current_segment_id.segment_index++;
current_ring.push_back(p);
- return current_ring.size();
+ return static_cast<signed_size_type>(current_ring.size());
}
//-------------------------------------------------------------------------
@@ -836,7 +923,7 @@ struct buffered_piece_collection
piece pc;
pc.type = type;
- pc.index = boost::size(m_pieces);
+ pc.index = static_cast<signed_size_type>(boost::size(m_pieces));
pc.first_seg_id = current_segment_id;
// Assign left/right (for first/last piece per ring they will be re-assigned later)
@@ -862,11 +949,11 @@ struct buffered_piece_collection
return;
}
- BOOST_ASSERT(pc.first_seg_id.multi_index >= 0);
- BOOST_ASSERT(pc.last_segment_index >= 0);
+ BOOST_GEOMETRY_ASSERT(pc.first_seg_id.multi_index >= 0);
+ BOOST_GEOMETRY_ASSERT(pc.last_segment_index >= 0);
pc.offsetted_count = pc.last_segment_index - pc.first_seg_id.segment_index;
- BOOST_ASSERT(pc.offsetted_count >= 0);
+ BOOST_GEOMETRY_ASSERT(pc.offsetted_count >= 0);
pc.robust_ring.reserve(pc.offsetted_count + helper_points_size);
@@ -915,11 +1002,10 @@ struct buffered_piece_collection
return;
}
- geometry::detail::envelope::envelope_range::apply(pc.robust_ring,
- pc.robust_envelope);
+ geometry::envelope(pc.robust_ring, pc.robust_envelope);
geometry::assign_inverse(pc.robust_offsetted_envelope);
- for (int i = 0; i < pc.offsetted_count; i++)
+ for (signed_size_type i = 0; i < pc.offsetted_count; i++)
{
geometry::expand(pc.robust_offsetted_envelope, pc.robust_ring[i]);
}
@@ -1010,7 +1096,7 @@ struct buffered_piece_collection
template <typename Range>
inline void add_range_to_piece(piece& pc, Range const& range, bool add_front)
{
- BOOST_ASSERT(boost::size(range) != 0u);
+ BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u);
typename Range::const_iterator it = boost::begin(range);
@@ -1046,7 +1132,7 @@ struct buffered_piece_collection
inline void add_side_piece(point_type const& p1, point_type const& p2,
Range const& range, bool first)
{
- BOOST_ASSERT(boost::size(range) >= 2u);
+ BOOST_GEOMETRY_ASSERT(boost::size(range) >= 2u);
piece& pc = create_piece(strategy::buffer::buffered_segment, ! first);
add_range_to_piece(pc, range, first);
@@ -1133,7 +1219,7 @@ struct buffered_piece_collection
robust_point_type any_point;
geometry::recalculate(any_point, point, m_robust_policy);
- int count_in_original = 0;
+ signed_size_type count_in_original = 0;
// Check of the robust point of this outputted ring is in
// any of the robust original rings
@@ -1279,7 +1365,7 @@ struct buffered_piece_collection
// Inner rings, for deflate, which do not have intersections, and
// which are outside originals, are skipped
// (other ones should be traversed)
- int index = 0;
+ signed_size_type index = 0;
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);
it != boost::end(offsetted_rings);
++it, ++index)
@@ -1287,8 +1373,12 @@ struct buffered_piece_collection
if (! it->has_intersections()
&& ! it->is_untouched_outside_original)
{
- ring_identifier id(0, index, -1);
- selected[id] = properties(*it);
+ properties p = properties(*it);
+ if (p.valid)
+ {
+ ring_identifier id(0, index, -1);
+ selected[id] = p;
+ }
}
}
@@ -1299,8 +1389,12 @@ struct buffered_piece_collection
it != boost::end(traversed_rings);
++it, ++index)
{
- ring_identifier id(2, index, -1);
- selected[id] = properties(*it);
+ properties p = properties(*it);
+ if (p.valid)
+ {
+ ring_identifier id(2, index, -1);
+ selected[id] = p;
+ }
}
detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true);