diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 15c5b23ec..c82b57685 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -28,6 +28,37 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace relate { +template ::type + >::value +> +struct simple_geometry +{ + template + static inline Geometry & apply(Geometry & g, Id const& ) { return g; } +}; + +template +struct simple_geometry +{ + template + static inline + typename boost::mpl::if_c + < + boost::is_const::value, + typename boost::range_value::type const&, + typename boost::range_value::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 @@ -150,9 +181,11 @@ struct linear_areal typedef typename std::vector::iterator turn_iterator; std::vector turns; -// TODO: INTEGRATE INTERRUPT POLICY WITH THE PASSED RESULT + interrupt_policy_linear_areal interrupt_policy(geometry2, result); - turns::get_turns::apply(turns, geometry1, geometry2); + turns::get_turns::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 + 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 + inline bool apply(Range const& turns) + { + typedef typename boost::range_iterator::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::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(m_result); + } + else if ( it->operations[0].operation == overlay::operation_continue ) + { + update(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(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 class turns_analyser diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 299bccf3f..cce713e5e 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -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 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(m_result); } } diff --git a/include/boost/geometry/algorithms/detail/relate/relate.hpp b/include/boost/geometry/algorithms/detail/relate/relate.hpp index 8219059f4..ac5b2fe99 100644 --- a/include/boost/geometry/algorithms/detail/relate/relate.hpp +++ b/include/boost/geometry/algorithms/detail/relate/relate.hpp @@ -131,6 +131,16 @@ struct relate : detail::relate::areal_linear {}; +template +struct relate + : detail::relate::linear_areal +{}; + +template +struct relate + : detail::relate::areal_linear +{}; + }} // namespace detail_dispatch::relate namespace detail { namespace relate { diff --git a/test/algorithms/relate.cpp b/test/algorithms/relate.cpp index ca6230393..3ebba1c9d 100644 --- a/test/algorithms/relate.cpp +++ b/test/algorithms/relate.cpp @@ -37,6 +37,7 @@ #include #include #include +#include //TEST #include @@ -436,6 +437,12 @@ void test_linestring_polygon() test_geometry("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("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("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("LINESTRING(9 1,10 5,9 9,1 9,1 1,9 1)", @@ -490,6 +497,28 @@ void test_linestring_polygon() "F1FFFF2F2.svg"); } +template +void test_linestring_multi_polygon() +{ + typedef bg::model::linestring

ls; + typedef bg::model::polygon

poly; + typedef bg::model::multi_polygon mpoly; + + test_geometry("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("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("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("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 void test_all() { @@ -501,6 +530,7 @@ void test_all() test_linestring_linestring

(); test_linestring_multi_linestring

(); test_linestring_polygon

(); + //test_linestring_multi_polygon

(); } int test_main( int , char* [] )