From 773331f6d95da043f0777975357466917253b9c2 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 11 Feb 2014 10:37:45 +0200 Subject: [PATCH] implementation of follower for linear geometries; added test files for difference of linear geometries; --- .../detail/turns/follow_linear_linear.hpp | 283 +++++++++ test/algorithms/difference1.cpp | 557 ++++++++++++++++++ test/algorithms/from_wkt.hpp | 14 + test/algorithms/test_difference1.hpp | 282 +++++++++ 4 files changed, 1136 insertions(+) create mode 100644 include/boost/geometry/algorithms/detail/turns/follow_linear_linear.hpp create mode 100644 test/algorithms/difference1.cpp create mode 100644 test/algorithms/from_wkt.hpp create mode 100644 test/algorithms/test_difference1.hpp diff --git a/include/boost/geometry/algorithms/detail/turns/follow_linear_linear.hpp b/include/boost/geometry/algorithms/detail/turns/follow_linear_linear.hpp new file mode 100644 index 000000000..1638cf5ed --- /dev/null +++ b/include/boost/geometry/algorithms/detail/turns/follow_linear_linear.hpp @@ -0,0 +1,283 @@ +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIFFERENCE_FOLLOW_LINEAR_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIFFERENCE_FOLLOW_LINEAR_LINEAR_HPP + +namespace boost { namespace geometry +{ + +namespace detail { namespace turns +{ + +namespace following +{ + +// follower for linear/linear geometries set operations + + + + +template +static inline bool is_entering(Turn const& turn, Operation const& op) +{ + if ( turn.method != overlay::method_touch && + turn.method != overlay::method_touch_interior ) + { + return false; + } + return op.operation == overlay::operation_intersection; +} + + + +template +< + typename Turn, + typename Operation, + typename LineString1, + typename LineString2 +> +static inline bool is_staying_inside(Turn const& turn, Operation const& op, + bool entered, bool first, + LineString1 const& linestring1, + LineString2 const& linestring2) + +{ + if ( !entered ) + { + return false; + } + + if ( turn.method != overlay::method_equal && + turn.method != overlay::method_collinear ) + { + // The normal case, this is completely covered with entering/leaving + // so stay out of this time consuming "covered_by" + return false; + } + return op.operation == overlay::operation_continue; +} + + + +template +< + typename Turn, + typename Operation, + typename Linestring1, + typename Linestring2 +> +static inline bool is_leaving(Turn const& turn, Operation const& op, + Operation const& reverse_op, + bool entered, bool first, + Linestring1 const& linestring1, + Linestring2 const& linestring2) +{ + if ( !entered ) + { + return false; + } + + if ( turn.method != overlay::method_touch && + turn.method != overlay::method_touch_interior && + turn.method != overlay::method_equal && + turn.method != overlay::method_collinear ) + { + return false; + } + + if ( op.operation == overlay::operation_blocked ) + { + return true; + } + + if ( op.operation != overlay::operation_union ) + { + return false; + } + + if ( turn.operations[1].operation == overlay::operation_intersection ) + { + return true; + } + + BOOST_CHECK( turn.operations[1].operation == overlay::operation_union || + turn.operations[1].operation == overlay::operation_blocked ); + + return reverse_op.operation == overlay::operation_intersection; +} + + + +template +< + typename LineStringOut, + typename MultiLineString1, + typename MultiLineString2, + overlay_type OverlayType +> +class follow +{ +protected: + typedef typename point_type::type PointOut; + typedef overlay::traversal_turn_info turn_info; + + typedef typename boost::range_value::type LineString1; + typedef typename boost::range_value::type LineString2; + + typedef typename boost::range_iterator + < + typename turn_info::container_type + >::type turn_operation_iterator_type; + + typedef detail::overlay::following::action_selector action; + +public: + template + static inline OutputIterator apply(MultiLineString1& multilinestring1, + MultiLineString2& multilinestring2, + Turns& turns, + Turns& reverse_turns, + OutputIterator oit) + { + BOOST_CHECK( boost::size(turns) == boost::size(reverse_turns) ); + + typedef typename Turns::iterator TurnIt; + + // Iterate through all intersection points (they are + // ordered along the each line) + + LineStringOut current_piece; + geometry::segment_identifier current_segment_id(0, -1, -1, -1); + int current_multi_id = -1; + // int current_other_multi_id = -1; + + bool entered = false; + bool first = true; + bool first_turn = true; + std::size_t enter_count = 0; + + // dummy initialization + LineString1& ls1 = *boost::begin(multilinestring1); + + TurnIt it = boost::begin(turns); + TurnIt it_r = boost::begin(reverse_turns); + for (; it != boost::end(turns); ++it, ++it_r) + { + turn_operation_iterator_type iit = boost::begin(it->operations); + turn_operation_iterator_type iit_r = boost::begin(it_r->operations); + ++iit_r; + + std::cout << std::endl; + std::cout << "current multi index: " << current_multi_id + << std::endl; + + std::cout << "processing turn with multi index: " + << iit->seg_id.multi_index + << std::endl; + + + if ( iit->seg_id.multi_index != current_multi_id ) + { + if ( first_turn ) + { + first_turn = false; + current_multi_id = iit->seg_id.multi_index; + ls1 = *(boost::begin(multilinestring1) + current_multi_id); + } + else + { + std::cout << "=================" << std::endl; + std::cout << "change of multi index: " + << current_multi_id << ' ' + << iit->seg_id.multi_index + << std::endl; + if (action::is_entered(entered)) + { + geometry::copy_segments(ls1, current_segment_id, + boost::size(ls1) - 1, + current_piece); + } + + // Output the last one, if applicable + if (::boost::size(current_piece) > 1) + { + *oit++ = current_piece; + } + + first = true; + entered = false; + enter_count = 0; + current_segment_id = geometry::segment_identifier(0, -1, -1, -1); + geometry::clear(current_piece); + current_multi_id = iit->seg_id.multi_index; + ls1 = *(boost::begin(multilinestring1) + current_multi_id); + } + } + + LineString2 const& ls2 = + *(boost::begin(multilinestring2) + iit->other_id.multi_index); + + if ( is_entering(*it, *iit) ) + { + detail::overlay::debug_traverse(*it, *iit, "-> Entering"); + + entered = true; + if ( enter_count == 0 ) + { + action::enter(current_piece, ls1, current_segment_id, + iit->seg_id.segment_index, + it->point, *iit, oit); + } + ++enter_count; + } + else if ( is_staying_inside(*it, *iit, entered, first, ls1, ls2) ) + { + detail::overlay::debug_traverse(*it, *iit, "-> Staying inside"); + + entered = true; + } + else if ( is_leaving(*it, *iit, *iit_r, entered, first, ls1, ls2) ) + { + detail::overlay::debug_traverse(*it, *iit, "-> Leaving"); + + --enter_count; + if ( enter_count == 0 ) + { + entered = false; + action::leave(current_piece, ls1, current_segment_id, + iit->seg_id.segment_index, + it->point, *iit, oit); + } + } + first = false; + } + + std::cout << "***enter count: " << enter_count << std::endl; + BOOST_CHECK( enter_count == 0 ); + if (action::is_entered(entered)) + { + geometry::copy_segments(ls1, current_segment_id, + boost::size(ls1) - 1, + current_piece); + } + + // Output the last one, if applicable + if (::boost::size(current_piece) > 1) + { + *oit++ = current_piece; + } + + return oit; + } +}; + + + + +} // namespace following + +}} // namespace detail::turns + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIFFERENCE_FOLLOW_LINEAR_LINEAR_HPP diff --git a/test/algorithms/difference1.cpp b/test/algorithms/difference1.cpp new file mode 100644 index 000000000..a9e8dac17 --- /dev/null +++ b/test/algorithms/difference1.cpp @@ -0,0 +1,557 @@ +#include + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_difference +#endif + +#include + +#include "test_difference1.hpp" + +#include +#include +#include "/home/mkaravel/bg/boost/geometry/mysql/algorithms/difference.hpp" + +typedef bg::model::point point_type; +typedef bg::model::segment segment_type; +typedef bg::model::linestring linestring_type; +typedef bg::model::multi_linestring multi_linestring_type; + + + +//=========================================================================== +//=========================================================================== +//=========================================================================== + + +#if 1 +BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** LINESTRING / LINESTRING DIFFERENCE ***" << std::endl; + std::cout << std::endl; +#endif + + typedef linestring_type L; + typedef multi_linestring_type ML; + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,5 0)"), + from_wkt("LINESTRING(3 0,4 0)"), + from_wkt("MULTILINESTRING((0 0,3 0),(4 0,5 0))"), + "lldf01.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(3 0,4 0)"), + from_wkt("LINESTRING(0 0,5 0)"), + from_wkt("MULTILINESTRING()"), + "lldf01-1.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,4 0)"), + from_wkt("LINESTRING(3 0,6 0)"), + from_wkt("MULTILINESTRING((0 0,3 0))"), + "lldf01-2.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(3 0,6 0)"), + from_wkt("LINESTRING(0 0,4 0)"), + from_wkt("MULTILINESTRING((4 0,6 0))"), + "lldf01-3.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,6 0)"), + from_wkt("LINESTRING(0 0,4 0)"), + from_wkt("MULTILINESTRING((4 0,6 0))"), + "lldf01-4.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,4 0)"), + from_wkt("LINESTRING(0 0,6 0)"), + from_wkt("MULTILINESTRING()"), + "lldf01-5.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,20 0)"), + from_wkt("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"), + from_wkt("MULTILINESTRING((0 0,4 0),(5 0,20 0))"), + "lldf01-6.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-20 0,20 0)"), + from_wkt("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"), + from_wkt("MULTILINESTRING((-20 0,4 0),(5 0,20 0))"), + "lldf01-7.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,4 0)"), + from_wkt("LINESTRING(2 0,4 0)"), + from_wkt("MULTILINESTRING((0 0,2 0))"), + "lldf01-8.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(2 0,4 0)"), + from_wkt("LINESTRING(0 0,4 0)"), + from_wkt("MULTILINESTRING()"), + "lldf01-9.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,2 0)"), + from_wkt("LINESTRING(4 0,5 0)"), + from_wkt("MULTILINESTRING((0 0,2 0))"), + "lldf01-10.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,2 0)"), + from_wkt("LINESTRING(2 0,5 0)"), + from_wkt("MULTILINESTRING((0 0,2 0))"), + "lldf01-11.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,6 0)"), + from_wkt("LINESTRING(2 0,4 0,5 0)"), + from_wkt("MULTILINESTRING((0 0,2 0),(5 0,6 0))"), + "lldf01-12.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,1 0,5 5,10 5,15 0)"), + from_wkt("LINESTRING(-1 6,0 5,15 5)"), + from_wkt("MULTILINESTRING((0 0,1 0,5 5),(10 5,15 0))"), + "lldf02.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0)"), + from_wkt("LINESTRING(-1 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0))"), + "lldf03.svg"); + + // to be removed + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0)"), + from_wkt("LINESTRING(30 0,-1 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0))")); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,1 0,5 5,10 5,15 0,20 0)"), + from_wkt("LINESTRING(-1 0,30 0)"), + from_wkt("MULTILINESTRING((1 0,5 5,10 5,15 0))"), + "lldf04.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,25 1)"), + from_wkt("LINESTRING(-1 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\ + (20 0,25 1))"), + "lldf05.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0)"), + from_wkt("LINESTRING(-1 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0))"), + "lldf05-1.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"), + from_wkt("LINESTRING(-1 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\ + (30 0,31 0))"), + "lldf06.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"), + from_wkt("LINESTRING(-1 0,25 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\ + (30 0,31 0))"), + "lldf07.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"), + from_wkt("LINESTRING(-1 0,19 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\ + (30 0,31 0))"), + "lldf08.svg"); + + // to be removed + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"), + from_wkt("LINESTRING(30 0,-1 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\ + (30 0,31 0))"), + "lldf-ToBeRemoved1.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"), + from_wkt("LINESTRING(-1 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\ + (30 0,31 1))"), + "lldf09.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"), + from_wkt("LINESTRING(-1 -1,0 0,1 0,2 1,3 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\ + (30 0,31 1))"), + "lldf10.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,20 0,30 0,31 1)"), + from_wkt("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(2 0,3 0),\ + (4 0,5 5,10 5,15 0),(30 0,31 1))"), + "lldf11.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)"), + from_wkt("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"), + from_wkt("MULTILINESTRING((-1 1,0 0),(2 0,3 0),\ + (4 0,5 5,10 5,15 0),(30 0,31 0))"), + "lldf11-1.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,2 0,3 1)"), + from_wkt("LINESTRING(0 0,2 0,3 1)"), + from_wkt("MULTILINESTRING()"), + "lldf12.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,2 0,3 1)"), + from_wkt("LINESTRING(3 1,2 0,0 0)"), + from_wkt("MULTILINESTRING()"), + "lldf12-1.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,1 0,2 1,3 5,4 0)"), + from_wkt("LINESTRING(1 0,2 1,3 5,4 0,5 10)"), + from_wkt("MULTILINESTRING((0 0,1 0))"), + "lldf13.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,1 0,2 0,2.5 0,3 1)"), + from_wkt("LINESTRING(0 0,2 0,2.5 0,3 1)"), + from_wkt("MULTILINESTRING()"), + "lldf14.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,1 0,2 1,3 5,4 0)"), + from_wkt("LINESTRING(1 0,2 1,3 5)"), + from_wkt("MULTILINESTRING((0 0,1 0),(3 5,4 0))"), + "lldf15.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,1 0,2 1,3 2)"), + from_wkt("LINESTRING(0.5 0,1 0,3 2,4 5)"), + from_wkt("MULTILINESTRING((0 0,0.5 0))"), + "lldf16.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,1 0,2 1,3 2)"), + from_wkt("LINESTRING(4 5,3 2,1 0,0.5 0)"), + from_wkt("MULTILINESTRING((0 0,0.5 0))"), + "lldf16-r.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,10 0,20 1,30 1)"), + from_wkt("LINESTRING(1 1,2 0,3 1,20 1,25 1)"), + from_wkt("MULTILINESTRING((0 0,10 0,20 1),(25 1,30 1))"), + "lldf17.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,10 0,20 1,21 0,30 0)"), + from_wkt("LINESTRING(1 1,2 0,3 1,20 1,25 0)"), + from_wkt("MULTILINESTRING((0 0,10 0,20 1,21 0,30 0))"), + "lldf18.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 1)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(5 1,4 0,4 1,20 1,5 0,1 0)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19-r.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(1 0,5 0,20 1,4 1,4 0)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19a.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(4 0,4 1,20 1,5 0,1 0)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19a-r.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19b.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,6 1)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19c.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19d.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0,3 1)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19e.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,5 1)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19f.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(5 1,5 0,4 0,4 1,20 1,5 0,1 0)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19f-r.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(1 0,5 0,20 1,4 1,5 0,5 1)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19g.svg"); + + test_difference_of_linestrings() + (from_wkt("LINESTRING(0 0,30 0)"), + from_wkt("LINESTRING(5 1,5 0,4 1,20 1,5 0,1 0)"), + from_wkt("MULTILINESTRING((0 0,1 0),(5 0,30 0))"), + "lldf19g-r.svg"); +} +#endif + + +#if 1 +BOOST_AUTO_TEST_CASE( test_difference_multilinestring_multilinestring ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** MULTILINESTRING / MULTILINESTRING DIFFERENCE ***" + << std::endl; + std::cout << std::endl; +#endif + + typedef multi_linestring_type ML; + + // disjoint linestrings + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"), + from_wkt("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"), + from_wkt("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"), + "mlmldf01.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"), + from_wkt("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"), + from_wkt("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\ + (1 0,2 0),(4 0,7 0))"), + "mlmldf02.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"), + from_wkt("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"), + from_wkt("MULTILINESTRING((0 0,2 0),(5 0,10 0,20 1),\ + (1 0,2 0),(5 0,7 0))"), + "mlmldf03.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"), + from_wkt("MULTILINESTRING((1 1,2 0,4 0))"), + from_wkt("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\ + (1 0,2 0),(4 0,7 0))"), + "mlmldf04.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\ + (10 10,20 10,30 20))"), + from_wkt("MULTILINESTRING((1 1,2 0,4 0),\ + (10 20,15 10,25 10,30 15))"), + from_wkt("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\ + (1 0,2 0),(4 0,7 0),(10 10,15 10),(20 10,30 20))"), + "mlmldf05.svg" + ); + + //bug + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\ + (10 10,20 10,30 20))"), + from_wkt("MULTILINESTRING((1 1,2 0,4 0),\ + (-1 -1,0 0,9 0,11 10,12 10,13 0.3,14 0.4,15 0.5),\ + (10 20,15 10,25 10,30 15))"), + from_wkt("MULTILINESTRING((9 0,10 0,13 0.3),(15 0.5,20 1),\ + (4 0,7 0),(10 10,11 10),(12 10,15 10),(20 10,30 20))"), + "mlmldf06.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,101 0))"), + from_wkt("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"), + from_wkt("MULTILINESTRING((0 0,1 0))"), + "mlmldf07.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((-1 1,0 0,101 0))"), + from_wkt("MULTILINESTRING((-1 -1,0 0,50 0),\ + (19 -1,20 0,101 0,200 -1))"), + from_wkt("MULTILINESTRING((-1 1,0 0))"), + "mlmldf07a.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,101 0))"), + from_wkt("MULTILINESTRING((-1 -1,0 0,50 0),\ + (19 -1,20 0,101 0,200 -1))"), + from_wkt("MULTILINESTRING()"), + "mlmldf07b.svg" + ); + + //bug + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,101 0))"), + from_wkt("MULTILINESTRING((0 1,1 1,2 0),\ + (-1 -1,1 0,101 0,200 -1))"), + from_wkt("MULTILINESTRING((0 0,1 0))"), + "mlmldf08.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,1 0,2 0.5,3 0,101 0))"), + from_wkt("MULTILINESTRING((0 1,1 1,2 0.5),\ + (-1 -1,1 0,101 0,200 -1))"), + from_wkt("MULTILINESTRING((0 0,1 0,2 0.5,3 0))"), + "mlmldf09.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,1 0,1.5 0,2 0.5,3 0,101 0))"), + from_wkt("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\ + (-1 -1,1 0,101 0,200 -1))"), + from_wkt("MULTILINESTRING((0 0,1 0),(1.5 0,2 0.5,3 0))"), + "mlmldf10.svg" + ); + + //bug + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,1 1,100 1,101 0),\ + (0 0,101 0))"), + from_wkt("MULTILINESTRING((1 0,1 1,2 1,3 0,4 0,5 1,6 1,\ + 7 0,8 0,9 1,10 1,11 0,12 0,13 1,14 1,15 0),\ + (-1 -1,1 0,101 0,200 -1))"), + from_wkt("MULTILINESTRING((0 0,1 1),(2 1,5 1),(6 1,9 1),\ + (10 1,13 1),(14 1,100 1,101 0),(0 0,1 0))"), + "mlmldf11.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,20 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\ + (3 1,4 0,16 0,17 1))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,20 0))"), + "mlmldf12.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,20 0))"), + from_wkt("MULTILINESTRING((1 0,19 0,20 1),\ + (2 0,18 0,19 1),(3 0,17 0,18 1),\ + (4 0,16 0,17 1))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,20 0))"), + "mlmldf13.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,20 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\ + 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,20 0))"), + "mlmldf14.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,20 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (2 2,4 2,6 0))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,20 0))"), + "mlmldf15.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,20 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (6 0,4 2,2 2))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,20 0))"), + "mlmldf15a.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,20 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (2 2,4 2,5 0,6 0))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,20 0))"), + "mlmldf16.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,20 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (6 0,5 0,4 2,2 2))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,20 0))"), + "mlmldf16a.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,30 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (2 2,4 0,5 2,20 2,25 0))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,30 0))"), + "mlmldf17.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,30 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (2 2,4 0,5 2,20 2,25 0,26 2))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,30 0))"), + "mlmldf17a.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,30 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (2 2,5 -1,15 2,18 0))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,30 0))"), + "mlmldf18.svg" + ); + + test_difference_of_multilinestrings() + (from_wkt("MULTILINESTRING((0 0,18 0,19 0,30 0))"), + from_wkt("MULTILINESTRING((0 1,1 0,19 0,20 1),\ + (2 2,5 -1,15 2,18 0))"), + from_wkt("MULTILINESTRING((0 0,1 0),(19 0,30 0))"), + "mlmldf18a.svg" + ); + +} +#endif diff --git a/test/algorithms/from_wkt.hpp b/test/algorithms/from_wkt.hpp new file mode 100644 index 000000000..c25fe1fdb --- /dev/null +++ b/test/algorithms/from_wkt.hpp @@ -0,0 +1,14 @@ +#ifndef BOOST_GEOMETRY_TEST_MYSQL_FROM_WKT_HPP +#define BOOST_GEOMETRY_TEST_MYSQL_FROM_WKT_HPP + +#include + +template +Geometry from_wkt(std::string const& wkt) +{ + Geometry res; + boost::geometry::read_wkt(wkt, res); + return res; +} + +#endif // BOOST_GEOMETRY_TEST_MYSQL_FROM_WKT_HPP diff --git a/test/algorithms/test_difference1.hpp b/test/algorithms/test_difference1.hpp new file mode 100644 index 000000000..fcdc12aa2 --- /dev/null +++ b/test/algorithms/test_difference1.hpp @@ -0,0 +1,282 @@ +#ifndef BOOST_GEOMETRY_TEST_DIFFERENCE1_HPP +#define BOOST_GEOMETRY_TEST_DIFFERENCE1_HPP + +#include "from_wkt.hpp" +#include +#include + +//#include "to_svg.hpp" +#include +#include + + +namespace bg = ::boost::geometry; + +template +struct multilinestring_equals +{ + static inline + bool apply(MultiLinestring1 const& mls1, MultiLinestring2 const& mls2) + { + BOOST_CHECK(boost::size(mls1) == boost::size(mls2)); + + typedef typename boost::range_iterator + < + MultiLinestring1 const + >::type ls1_iterator; + + typedef typename boost::range_iterator + < + MultiLinestring2 const + >::type ls2_iterator; + + typedef typename boost::range_value::type Linestring1; + + typedef typename boost::range_value::type Linestring2; + + typedef typename boost::range_iterator + < + Linestring1 const + >::type pt1_iterator; + + typedef typename boost::range_iterator + < + Linestring2 const + >::type pt2_iterator; + + + if ( boost::size(mls1) == boost::size(mls2) ) + { + ls1_iterator it1 = boost::begin(mls1); + ls2_iterator it2 = boost::begin(mls2); + for (; it1 != boost::end(mls1); ++it1, ++it2) + { + BOOST_CHECK( boost::size(*it1) == boost::size(*it2) ); + if ( boost::size(*it1) == boost::size(*it2) ) + { + pt1_iterator pit1 = boost::begin(*it1); + pt2_iterator pit2 = boost::begin(*it2); + for (; pit1 != boost::end(*it1); ++pit1, ++pit2) + { + BOOST_CHECK( bg::equals(*pit1, *pit2) ); + } + } + } + } + return true; + } +}; + + +//================================================================== +//================================================================== +// difference of linestrings +//================================================================== +//================================================================== + +struct test_difference_of_linestrings +{ + template + < + typename Linestring1, typename Linestring2, + typename MultiLinestring + > + void base_test(Linestring1 const& linestring1, + Linestring2 const& linestring2, + MultiLinestring const& mls_diff) const + { + typedef typename boost::range_value::type Linestring; + typedef std::vector LinestringVector; + typedef std::deque LinestringDeque; + + MultiLinestring mls_output; + + LinestringVector ls_vector_output; + LinestringDeque ls_deque_output; + + bg::difference(linestring1, linestring2, mls_output); + + BOOST_CHECK((multilinestring_equals + < + MultiLinestring, MultiLinestring + >::apply(mls_diff, mls_output) + )); + +#if 0 + bg::difference(linestring1, linestring2, ls_vector_output); + bg::difference(linestring1, linestring2, ls_deque_output); + + BOOST_CHECK((multilinestring_equals + < + MultiLinestring, LinestringVector + >::apply(mls_diff, ls_vector_output) + )); + + BOOST_CHECK((multilinestring_equals + < + MultiLinestring, LinestringDeque + >::apply(mls_diff, ls_deque_output) + )); +#endif +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "Linestring #1: " << bg::wkt(linestring1) << std::endl; + std::cout << "Linestring #2: " << bg::wkt(linestring2) << std::endl; + std::cout << "difference : " << bg::wkt(mls_output) + << std::endl; + std::cout << std::endl; +#endif + } + + template + < + typename Linestring1, typename Linestring2, + typename MultiLinestringOut + > + void operator()(Linestring1 const& linestring1, + Linestring2 const& linestring2, + MultiLinestringOut const& mls_diff) const + { + Linestring1 rls1(linestring1); + bg::reverse(rls1); + + Linestring2 rls2(linestring2); + bg::reverse(rls2); + + base_test(linestring1, linestring2, mls_diff); + // base_test(linestring1, rls2, mls_diff); + // base_test(rls1, linestring2, mls_diff); + // base_test(rls1, rls2, mls_diff); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << std::endl; +#endif + } + + template + < + typename Linestring1, typename Linestring2, + typename MultiLinestringOut + > + void operator()(Linestring1 const& linestring1, + Linestring2 const& linestring2, + MultiLinestringOut const& mls_diff, + std::string const& svg_fname) const + { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "SVG file: " << svg_fname << std::endl; + // to_svg(linestring1, linestring2, svg_fname); +#endif + this->operator()(linestring1, linestring2, mls_diff); + } +}; + + +//================================================================== +//================================================================== +// difference of multilinestrings +//================================================================== +//================================================================== + +struct test_difference_of_multilinestrings +{ + template + < + typename MultiLinestring1, typename MultiLinestring2, + typename MultiLinestring + > + void base_test(MultiLinestring1 const& multilinestring1, + MultiLinestring2 const& multilinestring2, + MultiLinestring const& mls_diff) const + { + typedef typename boost::range_value::type Linestring; + typedef std::vector LinestringVector; + typedef std::deque LinestringDeque; + + MultiLinestring mls_output; + + LinestringVector ls_vector_output; + LinestringDeque ls_deque_output; + + bg::difference(multilinestring1, multilinestring2, mls_output); + + BOOST_CHECK((multilinestring_equals + < + MultiLinestring, MultiLinestring + >::apply(mls_diff, mls_output) + )); + +#if 0 + bg::difference(linestring1, linestring2, ls_vector_output); + bg::difference(linestring1, linestring2, ls_deque_output); + + BOOST_CHECK((multilinestring_equals + < + MultiLinestring, LinestringVector + >::apply(mls_diff, ls_vector_output) + )); + + BOOST_CHECK((multilinestring_equals + < + MultiLinestring, LinestringDeque + >::apply(mls_diff, ls_deque_output) + )); +#endif +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "MultiLinestring #1: " + << bg::wkt(multilinestring1) << std::endl; + std::cout << "MultiLinestring #2: " + << bg::wkt(multilinestring2) << std::endl; + std::cout << "difference : " << bg::wkt(mls_output) + << std::endl; + std::cout << std::endl; +#endif + } + + template + < + typename MultiLinestring1, typename MultiLinestring2, + typename MultiLinestringOut + > + void operator()(MultiLinestring1 const& multilinestring1, + MultiLinestring2 const& multilinestring2, + MultiLinestringOut const& mls_diff) const + { + MultiLinestring1 rls1(multilinestring1); + bg::reverse(rls1); + + MultiLinestring2 rls2(multilinestring2); + bg::reverse(rls2); + + base_test(multilinestring1, multilinestring2, mls_diff); + // base_test(linestring1, rls2, mls_diff); + // base_test(rls1, linestring2, mls_diff); + // base_test(rls1, rls2, mls_diff); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << std::endl; +#endif + } + + template + < + typename MultiLinestring1, typename MultiLinestring2, + typename MultiLinestringOut + > + void operator()(MultiLinestring1 const& multilinestring1, + MultiLinestring2 const& multilinestring2, + MultiLinestringOut const& mls_diff, + std::string const& svg_fname) const + { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "SVG file: " << svg_fname << std::endl; + // to_svg(multilinestring1, multilinestring2, svg_fname); +#endif + this->operator()(multilinestring1, multilinestring2, mls_diff); + } +}; + + + +#endif // BOOST_GEOMETRY_TEST_DIFFERENCE1_HPP