mirror of
https://github.com/boostorg/geometry.git
synced 2026-01-31 20:22:09 +00:00
[relate] add interrupt policy for L/A
This commit is contained in:
@@ -28,6 +28,37 @@ namespace boost { namespace geometry
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace relate {
|
||||
|
||||
template <typename Geometry,
|
||||
bool IsMulti = boost::is_base_of
|
||||
<
|
||||
multi_tag,
|
||||
typename geometry::tag<Geometry>::type
|
||||
>::value
|
||||
>
|
||||
struct simple_geometry
|
||||
{
|
||||
template <typename Id>
|
||||
static inline Geometry & apply(Geometry & g, Id const& ) { return g; }
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct simple_geometry<Geometry, true>
|
||||
{
|
||||
template <typename Id>
|
||||
static inline
|
||||
typename boost::mpl::if_c
|
||||
<
|
||||
boost::is_const<Geometry>::value,
|
||||
typename boost::range_value<Geometry>::type const&,
|
||||
typename boost::range_value<Geometry>::type
|
||||
>::type
|
||||
apply(Geometry & g, Id const& id)
|
||||
{
|
||||
BOOST_ASSERT(id.multi_index >= 0);
|
||||
return *(boost::begin(g) + id.multi_index);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: In the worst case for MultiLinestring/MultiPolygon this is O(NM)
|
||||
// Use the rtree in this case!
|
||||
template <typename Geometry2, typename Result, typename BoundaryChecker, bool TransposeResult>
|
||||
@@ -150,9 +181,11 @@ struct linear_areal
|
||||
typedef typename std::vector<turn_type>::iterator turn_iterator;
|
||||
std::vector<turn_type> turns;
|
||||
|
||||
// TODO: INTEGRATE INTERRUPT POLICY WITH THE PASSED RESULT
|
||||
interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
|
||||
|
||||
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2);
|
||||
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);
|
||||
if ( result.interrupt )
|
||||
return;
|
||||
|
||||
// TODO: reverse and close if needed!
|
||||
// ONLY IF THE ALGORITHM BELOW WANTS TO ACCESS THE POINTS OF SEGMENTS
|
||||
@@ -198,6 +231,58 @@ static const bool reverse2 = detail::overlay::do_reverse<geometry::point_order<G
|
||||
boundary_checker1);
|
||||
}
|
||||
|
||||
template <typename Areal, typename Result>
|
||||
class interrupt_policy_linear_areal
|
||||
{
|
||||
public:
|
||||
static bool const enabled = true;
|
||||
|
||||
interrupt_policy_linear_areal(Areal const& areal, Result & result)
|
||||
: m_result(result), m_areal(areal)
|
||||
{}
|
||||
|
||||
// TODO: since we update result for some operations here, we must not do it in the analyser!
|
||||
|
||||
template <typename Range>
|
||||
inline bool apply(Range const& turns)
|
||||
{
|
||||
typedef typename boost::range_iterator<Range const>::type iterator;
|
||||
|
||||
for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
|
||||
{
|
||||
if ( it->operations[0].operation == overlay::operation_intersection )
|
||||
{
|
||||
bool const no_interior_rings
|
||||
= boost::empty(
|
||||
geometry::interior_rings(
|
||||
simple_geometry<Areal const>::apply(m_areal, it->operations[1].seg_id)));
|
||||
|
||||
// WARNING! THIS IS TRUE ONLY IF THE POLYGON IS SIMPLE!
|
||||
// OR WITHOUT INTERIOR RINGS (AND OF COURSE VALID)
|
||||
if ( no_interior_rings )
|
||||
update<interior, interior, '1', TransposeResult>(m_result);
|
||||
}
|
||||
else if ( it->operations[0].operation == overlay::operation_continue )
|
||||
{
|
||||
update<interior, boundary, '1', TransposeResult>(m_result);
|
||||
}
|
||||
else if ( ( it->operations[0].operation == overlay::operation_union
|
||||
|| it->operations[0].operation == overlay::operation_blocked )
|
||||
&& it->operations[0].position == overlay::position_middle )
|
||||
{
|
||||
// TODO: here we could also check the boundaries and set BB at this point
|
||||
update<interior, boundary, '0', TransposeResult>(m_result);
|
||||
}
|
||||
}
|
||||
|
||||
return m_result.interrupt;
|
||||
}
|
||||
|
||||
private:
|
||||
Result & m_result;
|
||||
Areal const& m_areal;
|
||||
};
|
||||
|
||||
// This analyser should be used like Input or SinglePass Iterator
|
||||
template <typename TurnInfo>
|
||||
class turns_analyser
|
||||
|
||||
@@ -276,6 +276,8 @@ struct linear_linear
|
||||
: m_result(result)
|
||||
{}
|
||||
|
||||
// TODO: since we update result for some operations here, we must not do it in the analyser!
|
||||
|
||||
template <typename Range>
|
||||
inline bool apply(Range const& turns)
|
||||
{
|
||||
@@ -295,7 +297,7 @@ struct linear_linear
|
||||
&& it->operations[0].position == overlay::position_middle
|
||||
&& it->operations[1].position == overlay::position_middle )
|
||||
{
|
||||
// TODO: here we could also check the boundaries and set IB,BI at this point
|
||||
// TODO: here we could also check the boundaries and set IB,BI,BB at this point
|
||||
update<interior, interior, '0'>(m_result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +131,16 @@ struct relate<Polygon, Linestring, polygon_tag, linestring_tag>
|
||||
: detail::relate::areal_linear<Polygon, Linestring>
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiPolygon>
|
||||
struct relate<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
|
||||
: detail::relate::linear_areal<Linestring, MultiPolygon>
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Linestring>
|
||||
struct relate<MultiPolygon, Linestring, multi_polygon_tag, linestring_tag>
|
||||
: detail::relate::areal_linear<MultiPolygon, Linestring>
|
||||
{};
|
||||
|
||||
}} // namespace detail_dispatch::relate
|
||||
|
||||
namespace detail { namespace relate {
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <boost/geometry.hpp>
|
||||
#include <boost/geometry/multi/geometries/multi_linestring.hpp>
|
||||
#include <boost/geometry/multi/geometries/multi_point.hpp>
|
||||
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
|
||||
|
||||
//TEST
|
||||
#include <to_svg.hpp>
|
||||
@@ -436,6 +437,12 @@ void test_linestring_polygon()
|
||||
test_geometry<ls, poly>("LINESTRING(2 8,10 5,2 2)",
|
||||
"POLYGON((0 0,0 10,10 10,10 0,0 0),(10 5,2 8,2 2,10 5))",
|
||||
"F1FF0F212");
|
||||
test_geometry<ls, poly>("LINESTRING(10 1,10 5,2 2)",
|
||||
"POLYGON((0 0,0 10,10 10,10 0,0 0),(10 5,2 8,2 2,10 5))",
|
||||
"F1FF0F212");
|
||||
test_geometry<ls, poly>("LINESTRING(10 1,10 5,2 8)",
|
||||
"POLYGON((0 0,0 10,10 10,10 0,0 0),(10 5,2 8,2 2,10 5))",
|
||||
"F1FF0F212");
|
||||
|
||||
// non-simple polygon with hole, linear ring
|
||||
test_geometry<ls, poly>("LINESTRING(9 1,10 5,9 9,1 9,1 1,9 1)",
|
||||
@@ -490,6 +497,28 @@ void test_linestring_polygon()
|
||||
"F1FFFF2F2.svg");
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
void test_linestring_multi_polygon()
|
||||
{
|
||||
typedef bg::model::linestring<P> ls;
|
||||
typedef bg::model::polygon<P> poly;
|
||||
typedef bg::model::multi_polygon<poly> mpoly;
|
||||
|
||||
test_geometry<ls, mpoly>("LINESTRING(10 1,10 5,10 9)",
|
||||
"MULTIPOLYGON(((0 20,0 30,10 30,10 20,0 20)),((0 0,0 10,10 10,10 0,0 0),(10 5,2 8,2 2,10 5)))",
|
||||
"F1FF0F212");
|
||||
test_geometry<ls, mpoly>("LINESTRING(10 1,10 5,10 9)",
|
||||
"MULTIPOLYGON(((0 20,0 30,10 30,10 20,0 20)),((0 0,0 10,10 10,10 0,0 0)))",
|
||||
"F1FF0F212");
|
||||
|
||||
test_geometry<ls, mpoly>("LINESTRING(10 1,10 5,2 2)",
|
||||
"MULTIPOLYGON(((0 20,0 30,10 30,10 20,0 20)),((0 0,0 10,10 10,10 0,0 0),(10 5,2 8,2 2,10 5)))",
|
||||
"F1FF0F212");
|
||||
test_geometry<ls, mpoly>("LINESTRING(10 1,10 5,2 2)",
|
||||
"MULTIPOLYGON(((0 20,0 30,10 30,10 20,0 20)),((0 0,0 10,10 10,10 0,0 0)))",
|
||||
"11F00F212");
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
void test_all()
|
||||
{
|
||||
@@ -501,6 +530,7 @@ void test_all()
|
||||
test_linestring_linestring<P>();
|
||||
test_linestring_multi_linestring<P>();
|
||||
test_linestring_polygon<P>();
|
||||
//test_linestring_multi_polygon<P>();
|
||||
}
|
||||
|
||||
int test_main( int , char* [] )
|
||||
|
||||
Reference in New Issue
Block a user