[relate] add interrupt policy for L/A

This commit is contained in:
Adam Wulkiewicz
2014-03-17 15:23:35 +01:00
parent b4417c40ad
commit d5935134ef
4 changed files with 130 additions and 3 deletions

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -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* [] )