diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 5b9562674..782639a96 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -574,6 +575,46 @@ struct intersection_insert_reversed }; +// dispatch for intersection(areal, areal, linear) +template +< + typename Geometry1, typename Geometry2, + typename LinestringOut, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag1, typename Tag2 +> +struct intersection_insert + < + Geometry1, Geometry2, + LinestringOut, + overlay_intersection, + Reverse1, Reverse2, ReverseOut, + Tag1, Tag2, linestring_tag, + true, true, false + > +{ + template + < + typename RobustPolicy, typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + detail::boundary_view view1(geometry1); + detail::boundary_view view2(geometry2); + + return detail::overlay::linear_linear_linestring + < + detail::boundary_view, + detail::boundary_view, + LinestringOut, + overlay_intersection + >::apply(view1, view2, robust_policy, oit, strategy); + } +}; // dispatch for non-areal geometries template diff --git a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index 73cef84c6..34517f659 100644 --- a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -157,13 +157,18 @@ protected: < typename Turns, typename LinearGeometry1, - typename LinearGeometry2 + typename LinearGeometry2, + typename RobustPolicy > static inline void compute_turns(Turns& turns, LinearGeometry1 const& linear1, - LinearGeometry2 const& linear2) + LinearGeometry2 const& linear2, + RobustPolicy const& robust_policy) { turns.clear(); + + detail::get_turns::no_interrupt_policy interrupt_policy; + geometry::detail::relate::turns::get_turns < LinearGeometry1, @@ -173,8 +178,9 @@ protected: LinearGeometry1, LinearGeometry2, assign_policy - > - >::apply(turns, linear1, linear2); + >, + RobustPolicy + >::apply(turns, linear1, linear2, interrupt_policy, robust_policy); } @@ -229,19 +235,27 @@ public: > static inline OutputIterator apply(Linear1 const& linear1, Linear2 const& linear2, - RobustPolicy const&, + RobustPolicy const& robust_policy, OutputIterator oit, Strategy const& ) { typedef typename detail::relate::turns::get_turns < - Linear1, Linear2 + Linear1, + Linear2, + detail::get_turns::get_turn_info_type + < + Linear1, + Linear2, + assign_policy + >, + RobustPolicy >::turn_info turn_info; typedef std::vector turns_container; turns_container turns; - compute_turns(turns, linear1, linear2); + compute_turns(turns, linear1, linear2, robust_policy); if ( turns.empty() ) { diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index 636c9756d..38d88b7d2 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -84,14 +84,30 @@ struct get_turns Geometry2 const& geometry2, InterruptPolicy & interrupt_policy) { - static const bool reverse1 = detail::overlay::do_reverse::value>::value; - static const bool reverse2 = detail::overlay::do_reverse::value>::value; - RobustPolicy robust_policy = geometry::get_rescale_policy < RobustPolicy >(geometry1, geometry2); + apply(turns, geometry1, geometry2, interrupt_policy, robust_policy); + } + + template + static inline void apply(Turns & turns, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + InterruptPolicy & interrupt_policy, + RobustPolicy const& robust_policy) + { + static const bool reverse1 = detail::overlay::do_reverse + < + geometry::point_order::value + >::value; + + static const bool reverse2 = detail::overlay::do_reverse + < + geometry::point_order::value + >::value; dispatch::get_turns < diff --git a/include/boost/geometry/views/detail/boundary_view.hpp b/include/boost/geometry/views/detail/boundary_view.hpp new file mode 100644 index 000000000..43bd5b202 --- /dev/null +++ b/include/boost/geometry/views/detail/boundary_view.hpp @@ -0,0 +1,16 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP +#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP + +#include +#include + +#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP diff --git a/include/boost/geometry/views/detail/boundary_view/implementation.hpp b/include/boost/geometry/views/detail/boundary_view/implementation.hpp new file mode 100644 index 000000000..e6a09afd6 --- /dev/null +++ b/include/boost/geometry/views/detail/boundary_view/implementation.hpp @@ -0,0 +1,466 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace boundary_views +{ + + +template +< + typename Polygon, + typename Value = typename ring_type::type, + typename Reference = typename ring_return_type::type, + typename Difference = typename boost::range_difference + < + typename boost::remove_reference + < + typename interior_return_type::type + >::type + >::type +> +class polygon_rings_iterator + : public boost::iterator_facade + < + polygon_rings_iterator, + Value, + boost::random_access_traversal_tag, + Reference, + Difference + > +{ + typedef typename boost::range_size + < + typename boost::remove_reference + < + typename interior_return_type::type + >::type + >::type size_type; + +public: + // default constructor + polygon_rings_iterator() + : m_polygon(NULL) + , m_index(0) + {} + + // for begin + polygon_rings_iterator(Polygon& polygon) + : m_polygon(boost::addressof(polygon)) + , m_index(0) + {} + + // for end + polygon_rings_iterator(Polygon& polygon, bool) + : m_polygon(boost::addressof(polygon)) + , m_index(static_cast(num_rings(polygon))) + {} + + template + < + typename OtherPolygon, + typename OtherValue, + typename OtherReference, + typename OtherDifference + > + polygon_rings_iterator(polygon_rings_iterator + < + OtherPolygon, + OtherValue, + OtherReference, + OtherDifference + > const& other) + : m_polygon(other.m_polygon) + , m_index(other.m_index) + { + static const bool is_convertible + = boost::is_convertible::value; + + BOOST_MPL_ASSERT_MSG((is_convertible), + NOT_CONVERTIBLE, + (types)); + } + +private: + friend class boost::iterator_core_access; + + template + < + typename OtherPolygon, + typename OtherValue, + typename OtherReference, + typename OtherDifference + > + friend class polygon_rings_iterator; + + + static inline std::size_t num_rings(Polygon const& polygon) + { + return geometry::num_interior_rings(polygon) + 1; + } + + inline Reference dereference() const + { + if (m_index == 0) + { + return exterior_ring(*m_polygon); + } + return range::at(interior_rings(*m_polygon), m_index - 1); + } + + template + < + typename OtherPolygon, + typename OtherValue, + typename OtherReference, + typename OtherDifference + > + inline bool equal(polygon_rings_iterator + < + OtherPolygon, + OtherValue, + OtherReference, + OtherDifference + > const& other) const + { + BOOST_GEOMETRY_ASSERT(m_polygon == other.m_polygon); + return m_index == other.m_index; + } + + inline void increment() + { + ++m_index; + } + + inline void decrement() + { + --m_index; + } + + template + < + typename OtherPolygon, + typename OtherValue, + typename OtherReference, + typename OtherDifference + > + inline Difference distance_to(polygon_rings_iterator + < + OtherPolygon, + OtherValue, + OtherReference, + OtherDifference + > const& other) const + { + return static_cast(other.m_index) + - static_cast(m_index); + } + + inline void advance(Difference n) + { + m_index += n; + } + +private: + Polygon* m_polygon; + size_type m_index; +}; + + +template +class ring_boundary : closeable_view::value>::type +{ +private: + typedef typename closeable_view::value>::type base_type; + +public: + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + + typedef linestring_tag tag_type; + + explicit ring_boundary(Ring& ring) + : base_type(ring) {} + + iterator begin() { return base_type::begin(); } + iterator end() { return base_type::end(); } + const_iterator begin() const { return base_type::begin(); } + const_iterator end() const { return base_type::end(); } +}; + + +template ::type> +struct num_rings +{}; + +template +struct num_rings +{ + static inline std::size_t apply(Polygon const& polygon) + { + return geometry::num_interior_rings(polygon) + 1; + } +}; + +template +struct num_rings +{ + static inline std::size_t apply(MultiPolygon const& multipolygon) + { + return geometry::num_interior_rings(multipolygon) + + static_cast(boost::size(multipolygon)); + } +}; + + +template ::type> +struct views_container_initializer +{}; + +template +struct views_container_initializer +{ + template + static inline void apply(Polygon const& polygon, BoundaryView* views) + { + typedef polygon_rings_iterator rings_iterator_type; + + std::uninitialized_copy(rings_iterator_type(polygon), + rings_iterator_type(polygon, true), + views); + } +}; + +template +class views_container_initializer +{ + typedef typename boost::mpl::if_ + < + boost::is_const, + typename boost::range_value::type const, + typename boost::range_value::type + >::type polygon_type; + + typedef polygon_rings_iterator inner_iterator_type; + + struct polygon_rings_begin + { + static inline inner_iterator_type apply(polygon_type& polygon) + { + return inner_iterator_type(polygon); + } + }; + + struct polygon_rings_end + { + static inline inner_iterator_type apply(polygon_type& polygon) + { + return inner_iterator_type(polygon, true); + } + }; + + typedef flatten_iterator + < + typename boost::range_iterator::type, + inner_iterator_type, + typename std::iterator_traits::value_type, + polygon_rings_begin, + polygon_rings_end, + typename std::iterator_traits::reference + > rings_iterator_type; + +public: + template + static inline void apply(MultiPolygon const& multipolygon, + BoundaryView* views) + { + rings_iterator_type first(boost::begin(multipolygon), + boost::end(multipolygon)); + rings_iterator_type last(boost::end(multipolygon)); + + std::uninitialized_copy(first, last, views); + } +}; + + +template +class areal_boundary +{ + typedef boundary_view::type> boundary_view_type; + typedef views_container_initializer exception_safe_initializer; + + template + struct automatic_deallocator + { + automatic_deallocator(T* ptr) : m_ptr(ptr) {} + + ~automatic_deallocator() + { + operator delete(m_ptr); + } + + inline void release() { m_ptr = NULL; } + + T* m_ptr; + }; + + inline void initialize_views(Areal const& areal) + { + // initialize number of rings + std::size_t n_rings = num_rings::apply(areal); + + if (n_rings == 0) + { + return; + } + + // allocate dynamic memory + boundary_view_type* views_ptr = static_cast + < + boundary_view_type* + >(operator new(sizeof(boundary_view_type) * n_rings)); + + // initialize; if exceptions are thrown by constructors + // they are handled automatically by automatic_deallocator + automatic_deallocator deallocator(views_ptr); + exception_safe_initializer::apply(areal, views_ptr); + deallocator.release(); + + // now initialize member variables safely + m_views = views_ptr; + m_num_rings = n_rings; + } + + // disallow copies and/or assignments + areal_boundary(areal_boundary const&); + areal_boundary& operator=(areal_boundary const&); + +public: + typedef boundary_view_type* iterator; + typedef boundary_view_type const* const_iterator; + + typedef multi_linestring_tag tag_type; + + explicit areal_boundary(Areal& areal) + : m_views(NULL) + , m_num_rings(0) + { + initialize_views(areal); + } + + ~areal_boundary() + { + boundary_view_type* last = m_views + m_num_rings; + for (boundary_view_type* it = m_views; it != last; ++it) + { + it->~boundary_view_type(); + } + operator delete(m_views); + } + + inline iterator begin() { return m_views; } + inline iterator end() { return m_views + m_num_rings; } + inline const_iterator begin() const { return m_views; } + inline const_iterator end() const { return m_views + m_num_rings; } + +private: + boundary_view_type* m_views; + std::size_t m_num_rings; +}; + + +}} // namespace detail::boundary_view +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch +{ + + +template +struct boundary_view + : detail::boundary_views::ring_boundary +{ + explicit boundary_view(Ring& ring) + : detail::boundary_views::ring_boundary(ring) + {} +}; + +template +struct boundary_view + : detail::boundary_views::areal_boundary +{ + explicit boundary_view(Polygon& polygon) + : detail::boundary_views::areal_boundary(polygon) + {} +}; + +template +struct boundary_view + : detail::boundary_views::areal_boundary +{ + explicit boundary_view(MultiPolygon& multipolygon) + : detail::boundary_views::areal_boundary + < + MultiPolygon + >(multipolygon) + {} +}; + + +} // namespace detail_dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP diff --git a/include/boost/geometry/views/detail/boundary_view/interface.hpp b/include/boost/geometry/views/detail/boundary_view/interface.hpp new file mode 100644 index 000000000..4d0b6d030 --- /dev/null +++ b/include/boost/geometry/views/detail/boundary_view/interface.hpp @@ -0,0 +1,70 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP +#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch +{ + +template ::type> +struct boundary_view + : not_implemented +{}; + +} // namespace detail_dispatch +#endif // DOXYGEN_NO_DISPATCH + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct boundary_view + : detail_dispatch::boundary_view +{ + explicit boundary_view(Geometry& geometry) + : detail_dispatch::boundary_view(geometry) + {} +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS +namespace traits +{ + +template +struct tag< geometry::detail::boundary_view > +{ + typedef typename detail_dispatch::boundary_view + < + Geometry + >::tag_type type; +}; + +} // namespace traits +#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP diff --git a/test/algorithms/set_operations/intersection/Jamfile.v2 b/test/algorithms/set_operations/intersection/Jamfile.v2 index 1d174881f..3535df852 100644 --- a/test/algorithms/set_operations/intersection/Jamfile.v2 +++ b/test/algorithms/set_operations/intersection/Jamfile.v2 @@ -17,6 +17,7 @@ test-suite boost-geometry-algorithms-intersection : [ run intersection.cpp : : : BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ] + [ run intersection_areal_areal_linear.cpp ] [ run intersection_linear_linear.cpp ] [ run intersection_pl_l.cpp ] [ run intersection_pl_pl.cpp ] diff --git a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp new file mode 100644 index 000000000..c83c794c0 --- /dev/null +++ b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp @@ -0,0 +1,391 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit test + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_intersection_linear_linear_areal +#endif + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#define BOOST_GEOMETRY_DEBUG_TURNS +#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER +#endif + +#include + +#include + +#include +#include +#include +#include +#include + +#include "test_intersection_linear_linear.hpp" + +typedef bg::model::point point_type; +typedef bg::model::multi_linestring + < + bg::model::linestring + > multi_linestring_type; + +typedef bg::model::ring open_ring_type; +typedef bg::model::polygon open_polygon_type; +typedef bg::model::multi_polygon open_multipolygon_type; + +typedef bg::model::ring closed_ring_type; +typedef bg::model::polygon closed_polygon_type; +typedef bg::model::multi_polygon closed_multipolygon_type; + + +template +< + typename OpenAreal1, + typename OpenAreal2, + typename ClosedAreal1, + typename ClosedAreal2, + typename MultiLinestring +> +struct test_intersection_aal +{ + static inline void apply(std::string const& case_id, + OpenAreal1 const& open_areal1, + OpenAreal2 const& open_areal2, + MultiLinestring const& expected1, + MultiLinestring const& expected2) + { + typedef test_intersection_of_geometries + < + OpenAreal1, OpenAreal2, MultiLinestring + > tester; + + tester::apply(open_areal1, open_areal2, expected1, expected2, case_id); + + ClosedAreal1 closed_areal1; + ClosedAreal2 closed_areal2; + bg::convert(open_areal1, closed_areal1); + bg::convert(open_areal2, closed_areal2); + + typedef test_intersection_of_geometries + < + ClosedAreal1, ClosedAreal2, MultiLinestring + > tester_of_closed; + + std::string case_id_closed = case_id + "-closed"; + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "testing closed areal geometries..." << std::endl; +#endif + tester_of_closed::apply(closed_areal1, closed_areal2, + expected1, expected2, case_id_closed); + } + + static inline void apply(std::string const& case_id, + OpenAreal1 const& open_areal1, + OpenAreal2 const& open_areal2, + MultiLinestring const& expected) + { + apply(case_id, open_areal1, open_areal2, expected, expected); + } +}; + + +BOOST_AUTO_TEST_CASE( test_intersection_ring_ring_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** RING / RING / LINEAR INTERSECTION ***" << std::endl; + std::cout << std::endl; +#endif + typedef open_ring_type OG; + typedef closed_ring_type CG; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("r-r-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); + + tester::apply + ("r-r-02", + from_wkt("POLYGON(())"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("r-r-03", + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("r-r-04", + from_wkt("POLYGON(())"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_ring_polygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** RING / POLYGON / LINEAR INTERSECTION ***" << std::endl; + std::cout << std::endl; +#endif + typedef open_ring_type OG1; + typedef open_polygon_type OG2; + typedef closed_ring_type CG1; + typedef closed_polygon_type CG2; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("r-pg-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_ring_multipolygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** RING / MULTIPOLYGON / LINEAR INTERSECTION ***" + << std::endl; + std::cout << std::endl; +#endif + typedef open_ring_type OG1; + typedef open_multipolygon_type OG2; + typedef closed_ring_type CG1; + typedef closed_multipolygon_type CG2; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("r-mpg-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_polygon_polygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** POLYGON / POLYGON / LINEAR INTERSECTION ***" << std::endl; + std::cout << std::endl; +#endif + typedef open_polygon_type OG; + typedef closed_polygon_type CG; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("pg-pg-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); + + tester::apply + ("pg-pg-02", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 2,2 7,7 7,7 2))"), + from_wkt("MULTILINESTRING((2 2,2 2),(2 2,2 7,7 7,7 2,2 2),(2 2,2 2))"), + from_wkt("MULTILINESTRING((2 2,2 2),(2 2,7 2,7 7,2 7,2 2),(2 2,2 2))") + ); + + tester::apply + ("pg-pg-03", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 3,2 6,6 6,6 3))"), + from_wkt("MULTILINESTRING((2 3,2 6),(2 3,2 3))") + ); + + tester::apply + ("pg-pg-04", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 3,2 7,6 7,6 3))"), + from_wkt("MULTILINESTRING((2 3,2 7,6 7),(2 3,2 3))") + ); + + tester::apply + ("pg-pg-05", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 3,2 7,7 7,7 3))"), + from_wkt("MULTILINESTRING((2 3,2 7,7 7,7 3),(2 3,2 3))") + ); + + tester::apply + ("pg-pg-06", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 3,2 7,7 7,7 3))"), + from_wkt("MULTILINESTRING((2 3,2 7,7 7,7 3),(2 3,2 3))") + ); + + tester::apply + ("pg-pg-07", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 5,5 7,7 5,5 2))"), + from_wkt("MULTILINESTRING((2 5,2 5),(5 7,5 7),(7 5,7 5),(5 2,5 2))") + ); + + tester::apply + ("pg-pg-08", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 5,4 7,6 7,7 5,5 2))"), + from_wkt("MULTILINESTRING((2 5,2 5),(4 7,6 7),(7 5,7 5),(5 2,5 2))") + ); + + tester::apply + ("pg-pg-09", + from_wkt("POLYGON(())"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("pg-pg-10", + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("pg-pg-11", + from_wkt("POLYGON(())"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("pg-pg-12", + from_wkt("POLYGON((),())"), + from_wkt("POLYGON((),(),())"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("pg-pg-13", + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0),())"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_polygon_multipolygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** POLYGON / MULTIPOLYGON / LINEAR INTERSECTION ***" + << std::endl; + std::cout << std::endl; +#endif + typedef open_polygon_type OG1; + typedef open_multipolygon_type OG2; + typedef closed_polygon_type CG1; + typedef closed_multipolygon_type CG2; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("pg-mpg-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_multipolygon_multipolygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** MULTIPOLYGON / MULTIPOLYGON / LINEAR INTERSECTION ***" + << std::endl; + std::cout << std::endl; +#endif + typedef open_multipolygon_type OG; + typedef closed_multipolygon_type CG; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("mpg-mpg-01", + from_wkt("MULTIPOLYGON(((0 0,0 2,2 2,2 0)))"), + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); + + tester::apply + ("mpg-mpg-02", + from_wkt("MULTIPOLYGON(((0 0,0 10,10 10,10 0),(2 2,8 2,8 8,2 8)))"), + from_wkt("MULTIPOLYGON(((2 4,2 6,8 6,8 4)))"), + from_wkt("MULTILINESTRING((2 4,2 4),(2 4,2 6),(8 6,8 4))") + ); + + tester::apply + ("mpg-mpg-03", + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("mpg-mpg-04", + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("mpg-mpg-05", + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("mpg-mpg-06", + from_wkt("MULTIPOLYGON((()),((),()))"), + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("mpg-mpg-07", + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0),(),()))"), + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTILINESTRING()") + ); +} diff --git a/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp b/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp index 07105aa8b..b4ade8310 100644 --- a/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp @@ -12,6 +12,8 @@ #include +#include + #include #include "../test_set_ops_linear_linear.hpp" #include @@ -69,7 +71,7 @@ private: std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl; std::cout << "intersection : " << bg::wkt(mls_output) << std::endl; std::cout << "expected intersection : " << bg::wkt(mls_int1) - << std::endl; + << " or: " << bg::wkt(mls_int2) << std::endl; std::cout << std::endl; std::cout << "************************************" << std::endl; std::cout << std::endl; @@ -120,8 +122,8 @@ private: std::cout << "Geometry #1: " << bg::wkt(geometry2) << std::endl; std::cout << "Geometry #2: " << bg::wkt(geometry1) << std::endl; std::cout << "intersection : " << bg::wkt(mls_output) << std::endl; - std::cout << "expected intersection : " << bg::wkt(mls_int2) - << std::endl; + std::cout << "expected intersection : " << bg::wkt(mls_int1) + << " or: " << bg::wkt(mls_int2) << std::endl; std::cout << std::endl; std::cout << "************************************" << std::endl; std::cout << std::endl; @@ -192,14 +194,27 @@ public: Geometry2 rg2(geometry2); bg::reverse(rg2); - test_get_turns_ll_invariance<>::apply(geometry1, geometry2); + typedef typename bg::tag_cast + < + Geometry1, bg::linear_tag + >::type tag1_type; + + typedef typename bg::tag_cast + < + Geometry2, bg::linear_tag + >::type tag2_type; + + bool const are_linear + = boost::is_same::value + && boost::is_same::value; + + test_get_turns_ll_invariance::apply(geometry1, geometry2); #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << std::endl << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl << std::endl; #endif - test_get_turns_ll_invariance<>::apply(rg1, geometry2); - + test_get_turns_ll_invariance::apply(rg1, geometry2); base_test(geometry1, geometry2, mls_int1, mls_int2, case_id, tolerance); // base_test(rg1, rg2, mls_int1, mls_int2); diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index b2a962ada..221bcd09e 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -32,6 +32,7 @@ namespace bg_turns = bg_detail::turns; template < + bool Enable = true, bool EnableRemoveDuplicateTurns = true, bool EnableDegenerateTurns = true > @@ -166,6 +167,17 @@ public: } }; - +template +class test_get_turns_ll_invariance +< + false, EnableRemoveDuplicateTurns, EnableDegenerateTurns +> +{ +public: + template + static inline void apply(Linear1 const&, Linear2 const&) + { + } +}; #endif // BOOST_GEOMETRY_TEST_GET_TURNS_LL_INVARIANCE_HPP