diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 9bf8473bf..886a9e572 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -28,27 +28,55 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace relate { +enum linestring_alt { linestring_exterior, linestring_point, linestring_closed, linestring_open }; + +template +linestring_alt linestring_simple_analysis(Linestring const& ls) +{ + std::size_t count = boost::size(ls); + if ( count == 0 ) + return linestring_exterior; + else if ( count == 1 ) + return linestring_point; + else + { + bool equal_fb = equals::equals_point_point(range::front(ls), range::back(ls)); + if ( equal_fb ) + // TODO: here the rest of points should be checked if they're equal with the first one + // and if they are, then it's a point + return linestring_closed; + else + return linestring_open; + } +} + template ::type> -struct has_disjoint_sub_geometries {}; +struct for_each_disjoint_linestring_if {}; template -struct has_disjoint_sub_geometries +struct for_each_disjoint_linestring_if { - template - static inline bool apply(TurnIt first, TurnIt last, Geometry const& /*geometry*/) + template + static inline bool apply(TurnIt first, TurnIt last, + Geometry const& /*geometry*/, + Pred & /*pred*/) { BOOST_ASSERT(first != last); + // TODO: check if has at least one valid turn - uix? + //return first != last; return false; } }; template -struct has_disjoint_sub_geometries +struct for_each_disjoint_linestring_if { - template - static inline bool apply(TurnIt first, TurnIt last, Geometry const& geometry) + template + static inline bool apply(TurnIt first, TurnIt last, + Geometry const& geometry, + Pred & pred) { BOOST_ASSERT(first != last); @@ -63,15 +91,54 @@ struct has_disjoint_sub_geometries detected_intersections[index] = true; } + bool found = false; + for ( std::vector::iterator it = detected_intersections.begin() ; it != detected_intersections.end() ; ++it ) { + // if there were no intersections for this multi_index if ( *it == false ) - return true; + { + found = true; + bool cont = pred( + *(boost::begin(geometry) + + std::distance(detected_intersections.begin(), it))); + if ( !cont ) + break; + } } + return found; + } +}; + +template +class disjoint_linestring_pred +{ +public: + disjoint_linestring_pred(BoundaryChecker & boundary_checker) + : m_boundary_checker_ptr(boost::addressof(boundary_checker)) + , m_boundary('F') + , m_interior('F') + {} + + template + bool operator()(Linestring const& linestring) + { + // TODO: check if there is boundary and interior and interior's dimension + m_boundary = '0'; + m_interior = '1'; + // TODO: return false only if boundary == 0 and interior == 1 return false; } + + char get_boundary() const { return m_boundary; } + char get_interior() const { return m_interior; } + +private: + BoundaryChecker * m_boundary_checker_ptr; + char m_boundary; + char m_interior; }; // update_result @@ -160,26 +227,33 @@ struct linear_linear return res; } -// TODO: this works bout we don't know what should be set exactly -// replace it with something like: for_each_disjoint_subgeometry - if ( has_disjoint_sub_geometries<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1) ) - { -// TODO: -// check if there is an interior and/or boundary - res.template update(); - res.template update(); - } - - if ( has_disjoint_sub_geometries<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2) ) - { -// TODO: -// check if there is an interior and/or boundary - res.template update(); - res.template update(); - } - boundary_checker boundary_checker1(geometry1); boundary_checker boundary_checker2(geometry2); + + disjoint_linestring_pred< boundary_checker > pred1(boundary_checker1); + disjoint_linestring_pred< boundary_checker > pred2(boundary_checker2); + + if ( for_each_disjoint_linestring_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1) ) + { + if ( pred1.get_interior() == '1' ) + res.template update(); + else if ( pred1.get_interior() == '0' ) + res.template update(); + + if ( pred1.get_boundary() == '0' ) + res.template update(); + } + + if ( for_each_disjoint_linestring_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2) ) + { + if ( pred2.get_interior() == '1' ) + res.template update(); + else if ( pred2.get_interior() == '0' ) + res.template update(); + + if ( pred2.get_boundary() == '0' ) + res.template update(); + } // 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