mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-09 23:22:10 +00:00
[buffer] use partition to check relation turn/piece
This commit is contained in:
@@ -103,6 +103,8 @@ struct buffer_turn_info
|
||||
buffer_turn_operation<Point, SegmentRatio>
|
||||
>
|
||||
{
|
||||
int turn_index; // TODO: this might go if partition can operate on non-const input
|
||||
|
||||
RobustPoint robust_point;
|
||||
RobustPoint mapped_robust_point; // alas... we still need to adapt our points, offsetting them 1 integer to be co-located with neighbours
|
||||
|
||||
@@ -119,7 +121,8 @@ struct buffer_turn_info
|
||||
#endif
|
||||
|
||||
inline buffer_turn_info()
|
||||
: location(location_ok)
|
||||
: turn_index(-1)
|
||||
, location(location_ok)
|
||||
, count_within(0)
|
||||
, count_on_offsetted(0)
|
||||
, count_on_helper(0)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <boost/geometry/extensions/algorithms/buffer/buffered_ring.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/buffer_policies.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/get_piece_turns.hpp>
|
||||
#include <boost/geometry/extensions/algorithms/buffer/turn_in_piece_visitor.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/assign_parents.hpp>
|
||||
@@ -104,34 +105,6 @@ struct check_original<point_tag>
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: move this
|
||||
template <typename Point>
|
||||
inline bool projection_on_segment(Point const& subject, Point const& p, Point const& q)
|
||||
{
|
||||
typedef Point vector_type;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
vector_type v = q;
|
||||
vector_type w = subject;
|
||||
subtract_point(v, p);
|
||||
subtract_point(w, p);
|
||||
|
||||
coordinate_type const zero = coordinate_type();
|
||||
coordinate_type const c1 = dot_product(w, v);
|
||||
|
||||
if (c1 < zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
coordinate_type const c2 = dot_product(v, v);
|
||||
if (c2 < c1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename Ring, typename RobustPolicy>
|
||||
struct buffered_piece_collection
|
||||
@@ -235,65 +208,9 @@ struct buffered_piece_collection
|
||||
: m_robust_policy(robust_policy)
|
||||
{}
|
||||
|
||||
inline bool on_offsetted(robust_point_type const& point, piece const& piece) const
|
||||
{
|
||||
for (int i = 1; i < piece.offsetted_count; i++)
|
||||
{
|
||||
robust_point_type const& previous = piece.robust_ring[i - 1];
|
||||
robust_point_type const& current = piece.robust_ring[i];
|
||||
int const side = side_strategy::apply(point, previous, current);
|
||||
if (side == 0)
|
||||
{
|
||||
// Collinear, check if projection falls on it
|
||||
if (projection_on_segment(point, previous, current))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void classify_turn(buffer_turn_info_type& turn, piece const& pc) const
|
||||
{
|
||||
if (pc.type == buffered_flat_end)
|
||||
{
|
||||
// Turns cannot be inside a flat end (though they can be on border)
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
// Don't compare against one of the two source-pieces
|
||||
if (turn.operations[i].piece_index == pc.index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int geometry_code = detail::within::point_in_geometry(turn.robust_point, pc.robust_ring);
|
||||
|
||||
if (geometry_code == 0)
|
||||
{
|
||||
if (! on_offsetted(turn.robust_point, pc))
|
||||
{
|
||||
// It is on the border but not on the offsetted ring.
|
||||
// Then it is somewhere on the helper-segments
|
||||
// Classify it as inside
|
||||
// TODO: for neighbouring flat ends this does not apply
|
||||
geometry_code = 1;
|
||||
turn.count_on_helper++;
|
||||
}
|
||||
}
|
||||
|
||||
switch (geometry_code)
|
||||
{
|
||||
case 1 : turn.count_within++; break;
|
||||
case 0 : turn.count_on_offsetted++; break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
template <typename OccupationMap>
|
||||
@@ -505,21 +422,19 @@ struct buffered_piece_collection
|
||||
|
||||
inline void classify_turns()
|
||||
{
|
||||
|
||||
// Check if it is inside any of the pieces
|
||||
// Now: quadratic
|
||||
// TODO: in partition.
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
{
|
||||
typename std::vector<piece>::const_iterator pit;
|
||||
for (pit = boost::begin(m_pieces);
|
||||
pit != boost::end(m_pieces);
|
||||
++pit)
|
||||
{
|
||||
classify_turn(*it, *pit);
|
||||
}
|
||||
}
|
||||
|
||||
turn_in_piece_visitor
|
||||
<
|
||||
turn_vector_type
|
||||
> visitor(m_turns);
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
model::box<robust_point_type>,
|
||||
turn_get_box, turn_ovelaps_box,
|
||||
piece_get_box, piece_ovelaps_box
|
||||
>::apply(m_turns, m_pieces, visitor);
|
||||
}
|
||||
|
||||
template <typename Turn>
|
||||
@@ -645,6 +560,7 @@ struct buffered_piece_collection
|
||||
it->mapped_robust_point = it->robust_point;
|
||||
|
||||
robust_turn turn;
|
||||
it->turn_index = index;
|
||||
turn.turn_index = index;
|
||||
turn.point = it->robust_point;
|
||||
for (int i = 0; i < 2; i++)
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
// 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_TURN_IN_PIECE_VISITOR
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR
|
||||
|
||||
#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 turn_get_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline void apply(Box& total, Turn const& turn)
|
||||
{
|
||||
geometry::expand(total, turn.robust_point);
|
||||
}
|
||||
};
|
||||
|
||||
struct turn_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline bool apply(Box const& box, Turn const& turn)
|
||||
{
|
||||
return ! geometry::disjoint(box, turn.robust_point);
|
||||
}
|
||||
};
|
||||
template <typename Turns>
|
||||
class turn_in_piece_visitor
|
||||
{
|
||||
Turns& m_turns; // because partition is currently operating on const input only
|
||||
|
||||
template <typename Point>
|
||||
static inline bool projection_on_segment(Point const& subject, Point const& p, Point const& q)
|
||||
{
|
||||
typedef Point vector_type;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
vector_type v = q;
|
||||
vector_type w = subject;
|
||||
subtract_point(v, p);
|
||||
subtract_point(w, p);
|
||||
|
||||
coordinate_type const zero = coordinate_type();
|
||||
coordinate_type const c1 = dot_product(w, v);
|
||||
|
||||
if (c1 < zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
coordinate_type const c2 = dot_product(v, v);
|
||||
if (c2 < c1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename Point, typename Piece>
|
||||
inline bool on_offsetted(Point const& point, Piece const& piece) const
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
|
||||
for (int i = 1; i < piece.offsetted_count; i++)
|
||||
{
|
||||
Point const& previous = piece.robust_ring[i - 1];
|
||||
Point const& current = piece.robust_ring[i];
|
||||
int const side = side_strategy::apply(point, previous, current);
|
||||
if (side == 0)
|
||||
{
|
||||
// Collinear, check if projection falls on it
|
||||
if (projection_on_segment(point, previous, current))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline turn_in_piece_visitor(Turns& turns)
|
||||
: m_turns(turns)
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Piece>
|
||||
inline void apply(Turn const& turn, Piece const& piece, bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
if (piece.type == buffered_flat_end)
|
||||
{
|
||||
// Turns cannot be inside a flat end (though they can be on border)
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
// Don't compare against one of the two source-pieces
|
||||
if (turn.operations[i].piece_index == piece.index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||
if (geometry_code == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||
if (geometry_code == 0)
|
||||
{
|
||||
if (! on_offsetted(turn.robust_point, piece))
|
||||
{
|
||||
// It is on the border but not on the offsetted ring.
|
||||
// Then it is somewhere on the helper-segments
|
||||
// Classify it as inside
|
||||
// TODO: for neighbouring flat ends this does not apply
|
||||
geometry_code = 1;
|
||||
mutable_turn.count_on_helper++;
|
||||
}
|
||||
}
|
||||
|
||||
switch (geometry_code)
|
||||
{
|
||||
case 1 : mutable_turn.count_within++; break;
|
||||
case 0 : mutable_turn.count_on_offsetted++; break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR
|
||||
Reference in New Issue
Block a user