mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-01 20:42:10 +00:00
[buffer] use monotonic sections for checking point-in-original
This can enhance performance with 20%
This commit is contained in:
@@ -203,6 +203,9 @@ struct buffered_piece_collection
|
||||
|
||||
struct robust_original
|
||||
{
|
||||
typedef robust_ring_type original_robust_ring_type;
|
||||
typedef geometry::sections<robust_box_type, 1> sections_type;
|
||||
|
||||
inline robust_original()
|
||||
: m_is_interior(false)
|
||||
, m_has_interiors(true)
|
||||
@@ -224,9 +227,7 @@ struct buffered_piece_collection
|
||||
|
||||
robust_ring_type m_ring;
|
||||
robust_box_type m_box;
|
||||
geometry::sections<robust_box_type, 1> m_sections;
|
||||
|
||||
typedef robust_ring_type original_robust_ring_type;
|
||||
sections_type m_sections;
|
||||
|
||||
bool m_is_interior;
|
||||
bool m_has_interiors;
|
||||
|
||||
@@ -73,20 +73,54 @@ template <typename Point, typename Original>
|
||||
inline int point_in_original(Point const& point, Original const& original)
|
||||
{
|
||||
typedef strategy::within::winding<Point> strategy_type;
|
||||
strategy_type strategy;
|
||||
|
||||
typedef typename Original::original_robust_ring_type ring_type;
|
||||
typedef typename Original::sections_type sections_type;
|
||||
typedef typename boost::range_iterator<ring_type const>::type iterator_type;
|
||||
typename strategy_type::state_type state;
|
||||
iterator_type it = boost::begin(original.m_ring);
|
||||
typedef typename boost::range_iterator<sections_type const>::type siterator_type;
|
||||
|
||||
for (iterator_type previous = it++;
|
||||
it != boost::end(original.m_ring);
|
||||
++previous, ++it)
|
||||
typename geometry::coordinate_type<Point>::type const point_y
|
||||
= geometry::get<1>(point);
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
|
||||
// Walk through all monotonic sections
|
||||
for (siterator_type sit = boost::begin(original.m_sections);
|
||||
sit != boost::end(original.m_sections);
|
||||
++sit)
|
||||
{
|
||||
if (! strategy.apply(point, *previous, *it, state))
|
||||
typename boost::range_value<sections_type const>::type const& section = *sit;
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_y >= geometry::get<min_corner, 1>(section.bounding_box)
|
||||
&& point_y <= geometry::get<max_corner, 1>(section.bounding_box))
|
||||
{
|
||||
break;
|
||||
// Walk through this section
|
||||
iterator_type it
|
||||
= boost::begin(original.m_ring) + section.begin_index;
|
||||
iterator_type const end
|
||||
= boost::begin(original.m_ring) + section.end_index + 1;
|
||||
for (iterator_type previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
if (! strategy.apply(point, *previous, *it, state))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Depending on sections.direction we can quit the inner loop
|
||||
typename geometry::coordinate_type<Point>::type const ring_y
|
||||
= geometry::get<1>(*it);
|
||||
|
||||
if (section.directions[0] == 1 && point_y < ring_y)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (section.directions[0] == -1 && point_y > ring_y)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user