[relate] add optimization for L/L ommitting parts of the algorithm if the result mustnot be updated

This commit is contained in:
Adam Wulkiewicz 2014-04-07 23:52:40 +02:00
parent cce6c71782
commit d76c94d643
3 changed files with 52 additions and 16 deletions

View File

@ -35,13 +35,28 @@ class disjoint_linestring_pred
public:
disjoint_linestring_pred(Result & res,
BoundaryChecker const& boundary_checker)
: m_result_ptr(boost::addressof(res))
, m_boundary_checker_ptr(boost::addressof(boundary_checker))
{}
: m_result(res)
, m_boundary_checker(boundary_checker)
, m_flags(0)
{
if ( ! may_update<interior, exterior, '1', TransposeResult>(m_result) )
{
m_flags |= 1;
}
if ( ! may_update<boundary, exterior, '0', TransposeResult>(m_result) )
{
m_flags |= 2;
}
}
template <typename Linestring>
bool operator()(Linestring const& linestring)
{
if ( m_flags == 3 )
{
return false;
}
std::size_t count = boost::size(linestring);
// invalid input
@ -52,25 +67,28 @@ public:
return true;
}
update<interior, exterior, '1', TransposeResult>(*m_result_ptr);
update<interior, exterior, '1', TransposeResult>(m_result);
m_flags |= 1;
// check if there is a boundary
if ( m_boundary_checker_ptr->template
if ( m_flags < 2
&& ( m_boundary_checker.template
is_endpoint_boundary<boundary_front>(range::front(linestring))
|| m_boundary_checker_ptr->template
is_endpoint_boundary<boundary_back>(range::back(linestring)) )
|| m_boundary_checker.template
is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )
{
update<boundary, exterior, '0', TransposeResult>(*m_result_ptr);
return false;
update<boundary, exterior, '0', TransposeResult>(m_result);
m_flags |= 2;
}
return !m_result_ptr->interrupt;
return m_flags != 3
&& ! m_result.interrupt;
}
private:
Result * m_result_ptr;
const BoundaryChecker * m_boundary_checker_ptr;
Result & m_result;
BoundaryChecker const& m_boundary_checker;
unsigned m_flags;
};
//enum linestring_kind { linestring_exterior, linestring_point, linestring_closed, linestring_open };
@ -239,8 +257,12 @@ struct linear_linear
// TODO: turns must be sorted and followed only if it's possible to go out and in on the same point
// for linear geometries union operation must be detected which I guess would be quite often
// TODO: ADD A CHECK TO THE RESULT INDICATING IF THE FIRST AND/OR SECOND GEOMETRY MUST BE ANALYSED
if ( may_update<interior, interior, '1'>(result)
|| may_update<interior, boundary, '0'>(result)
|| may_update<interior, exterior, '1'>(result)
|| may_update<boundary, interior, '0'>(result)
|| may_update<boundary, boundary, '0'>(result)
|| may_update<boundary, exterior, '0'>(result) )
{
// x, u, i, c
typedef turns::less
@ -262,6 +284,12 @@ struct linear_linear
if ( result.interrupt )
return;
if ( may_update<interior, interior, '1', true>(result)
|| may_update<interior, boundary, '0', true>(result)
|| may_update<interior, exterior, '1', true>(result)
|| may_update<boundary, interior, '0', true>(result)
|| may_update<boundary, boundary, '0', true>(result)
|| may_update<boundary, exterior, '0', true>(result) )
{
// x, u, i, c
typedef turns::less

View File

@ -35,6 +35,12 @@ namespace detail { namespace relate {
enum field { interior = 0, boundary = 1, exterior = 2 };
// TODO: IF THE RESULT IS UPDATED WITH THE MAX POSSIBLE VALUE FOR SOME PAIR OF GEOEMTRIES
// THE VALUE ALREADY STORED MUSN'T BE CHECKED
// update() calls chould be replaced with set() in those cases
// but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that
// so some additional function could be added, e.g. set_dim()
// matrix
// TODO add height?

View File

@ -348,10 +348,11 @@ void test_linestring_linestring()
// OTHER MASKS
{
namespace bgdr = bg::detail::relate;
ls ls1, ls2, ls3;
ls ls1, ls2, ls3, ls4;
bg::read_wkt("LINESTRING(0 0,2 0)", ls1);
bg::read_wkt("LINESTRING(2 0,4 0)", ls2);
bg::read_wkt("LINESTRING(1 0,1 1)", ls3);
bg::read_wkt("LINESTRING(1 0,4 0)", ls4);
BOOST_CHECK(bgdr::relate(ls1, ls2, bgdr::mask9("FT*******")
|| bgdr::mask9("F**T*****")
|| bgdr::mask9("F***T****")));
@ -361,6 +362,7 @@ void test_linestring_linestring()
BOOST_CHECK(bgdr::relate(ls3, ls1, bgdr::mask9("FT*******")
|| bgdr::mask9("F**T*****")
|| bgdr::mask9("F***T****")));
BOOST_CHECK(bgdr::relate(ls2, ls4, bgdr::mask9("T*F**F***"))); // within
}
}