From a0e56a6157bdac71a8e2fbe28b4a05f4c584e79f Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 11 Feb 2014 16:22:39 +0200 Subject: [PATCH] current implementation for difference of linear geometries (still a prototype); added some copyright headers and made minor fixes; --- .../detail/difference/linear_linear.hpp | 394 ++++++++++++++++++ .../detail/overlay/intersection_insert.hpp | 46 ++ .../algorithms/detail/relate/turns.hpp | 4 +- .../algorithms/detail/turns/print_turns.hpp | 1 + test/algorithms/difference1.cpp | 11 +- test/algorithms/test_difference1.hpp | 9 + 6 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/difference/linear_linear.hpp diff --git a/include/boost/geometry/algorithms/detail/difference/linear_linear.hpp b/include/boost/geometry/algorithms/detail/difference/linear_linear.hpp new file mode 100644 index 000000000..740218850 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/difference/linear_linear.hpp @@ -0,0 +1,394 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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_GEOMETRY_ALGORITHMS_DETAIL_DIFFERENCE_LINEAR_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIFFERENCE_LINEAR_LINEAR_HPP + +#include + +#include + +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace difference +{ + + +//=========================================================================== +//=========================================================================== +//=========================================================================== + + + +template +struct multilinestring_multilinestring_linestring +{ + typedef typename point_type::type PointOut; + typedef overlay::traversal_turn_info turn_info; + typedef std::vector Turns; + typedef typename Turns::iterator TurnIt; + typedef detail::get_turns::no_interrupt_policy InterruptPolicy; + + struct AssignPolicy + { + static bool const include_no_turn = false; + static bool const include_degenerate = false; + static bool const include_opposite = false; + + template + < + typename Info, + typename Point1, + typename Point2, + typename IntersectionInfo, + typename DirInfo + > + static inline void apply(Info& info, Point1 const& p1, Point2 const& p2, + IntersectionInfo const& ii, DirInfo const& di) + { + overlay::calculate_distance_policy::apply(info, p1, p2, ii, di); + } + }; + + struct IsContinueTurn + { + template + bool operator()(Turn const& turn) const + { + if ( turn.method != overlay::method_collinear && + turn.method != overlay::method_equal ) + { + return false; + } + overlay::operation_type op[2]; + op[0] = turn.operations[0].operation; + op[1] = turn.operations[1].operation; + + return + (op[0] == overlay::operation_continue || + op[0] == overlay::operation_opposite) && + (op[1] == overlay::operation_continue || + op[1] == overlay::operation_opposite); + } + }; + + + template + static inline void filter_turns(Turns& turns) + { +#if 1 + typedef typename Turns::iterator TurnIt; + + TurnIt new_end = std::remove_if(turns.begin(), turns.end(), + IsContinueTurn()); + turns.resize( std::distance(turns.begin(), new_end) ); +#endif + } + + + template + < + typename Linestring1, typename Linestring2, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Linestring1 const& multilinestring1, + Linestring2 const& multilinestring2, + OutputIterator oit, + Strategy const& ) + { + std::cout << "MultiLinestring-MultiLinestring difference" << std::endl; + + typedef geometry::model::multi_linestring MultiLinestringOut; + + MultiLinestringOut mls1, mls2; + geometry::convert(multilinestring1, mls1); + geometry::convert(multilinestring2, mls2); + + assert( boost::size(mls1) > 0 ); + assert( boost::size(mls2) > 0 ); + + + // canonical::apply(ls1); + // canonical::apply(ls2); + + // typedef typename point_type::type PointOut; + +#if 0 + typedef //overlay::assign_null_policy + overlay::calculate_distance_policy AssignPolicy; +#endif + // typedef //overlay::assign_null_policy + // detail::union_::assign_union_policy AssignPolicy; + + // typedef detail::disjoint::disjoint_interrupt_policy InterruptPolicy; + + Turns turns, reverse_turns; + + geometry::detail::relate::turns::get_turns + < + MultiLinestringOut, + MultiLinestringOut, + detail::get_turns::get_turn_info_type + < + MultiLinestringOut, + MultiLinestringOut, + AssignPolicy + > + >::apply(turns, mls1, mls2); + + MultiLinestringOut mls2_reverse = mls2; + geometry::reverse(mls2_reverse); + geometry::detail::relate::turns::get_turns + < + MultiLinestringOut, + MultiLinestringOut, + detail::get_turns::get_turn_info_type + < + MultiLinestringOut, + MultiLinestringOut, + AssignPolicy + > + >::apply(reverse_turns, mls1, mls2_reverse); + + if ( turns.empty() ) + { + // the two linestrings are disjoint; we return the first as is; + // canonical::apply(mls1); + std::cout << "NO INTERSECTIONS" << std::endl; + std::copy(mls1.begin(), mls1.end(), oit); + return oit; + } + + // remove turns that have no added value + filter_turns(turns); + filter_turns(reverse_turns); + + // sort by seg_id, distance, and operation + typedef detail::turns::less_seg_dist_other_op<> less; + std::sort(boost::begin(turns), boost::end(turns), less()); + + typedef + detail::turns::less_seg_dist_other_op > rev_less; + std::sort(boost::begin(reverse_turns), boost::end(reverse_turns), + rev_less()); + + +#if 1 + detail::turns::print_turns(mls1, mls2, turns); + std::cout << std::endl << std::endl; + detail::turns::print_turns(mls1, mls2_reverse, reverse_turns); +#endif + + return detail::turns::following::follow + < + LinestringOut, + MultiLinestringOut, + MultiLinestringOut, + overlay_difference + >::apply(mls1, mls2, turns, reverse_turns, oit); + } +}; + + +//=========================================================================== +//=========================================================================== +//=========================================================================== + + + + + +template +struct linestring_linestring_linestring +{ + typedef typename point_type::type PointOut; + typedef overlay::traversal_turn_info turn_info; + + + template + < + typename Linestring1, typename Linestring2, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Linestring1 const& linestring1, + Linestring2 const& linestring2, + OutputIterator oit, + Strategy const& strategy) + { + std::cout << "Linestring-Linestring difference" << std::endl; + +#if 1 + geometry::model::multi_linestring mls1; + geometry::model::multi_linestring mls2; + + mls1.push_back(linestring1); + mls2.push_back(linestring2); + + + return + multilinestring_multilinestring_linestring + < + LinestringOut + >::apply(mls1, mls2, oit, strategy); + +#else + LinestringOut ls1, ls2; + geometry::convert(linestring1, ls1); + geometry::convert(linestring2, ls2); + + assert( boost::size(ls1) > 1 ); + assert( boost::size(ls2) > 1 ); + + + // canonical::apply(ls1); + // canonical::apply(ls2); + + // typedef typename point_type::type PointOut; + + // typedef //overlay::assign_null_policy + // overlay::calculate_distance_policy AssignPolicy; + typedef //overlay::assign_null_policy + detail::union_::assign_union_policy AssignPolicy; + + typedef overlay::get_turn_info + < + PointOut, PointOut, turn_info, AssignPolicy + > TurnPolicy; + + typedef std::vector Turns; + typedef typename std::vector::iterator TurnIt; + typedef detail::get_turns::no_interrupt_policy InterruptPolicy; + // typedef detail::disjoint::disjoint_interrupt_policy InterruptPolicy; + + typedef geometry::model::multi_linestring MultiLinestringOut; + MultiLinestringOut mls_out; + + Turns turns; + InterruptPolicy interrupt_policy; + + geometry::get_turns + < + false, false, + AssignPolicy + >(ls1, ls2, turns, interrupt_policy); + + + if ( turns.empty() ) + { + // the two linestrings are disjoint; we return the first as is; + mls_out.push_back(ls1); + // canonical::apply(mls_out); + std::copy(mls_out.begin(), mls_out.end(), oit); + return oit; + } + + // sort by seg_id, distance, and operation + typedef overlay::turns::less_seg_dist_op less; + std::sort(boost::begin(turns), boost::end(turns), less()); + + + +#if 1 + detail::turns::print_turns(ls1, ls2, turns); +#endif + + LinestringOut current_piece; + geometry::segment_identifier current_segment_id(0, -1, -1, -1); + + // Iterate through all intersection points (they are ordered along the line) + + + typedef typename boost::range_iterator + < + typename turn_info::container_type + >::type turn_operation_iterator_type; + + typedef detail::overlay::following::action_selector + < + overlay_difference + > action; + + bool entered = false; + bool first = true; + for (TurnIt it = boost::begin(turns); it != boost::end(turns); ++it) + { + turn_operation_iterator_type iit = boost::begin(it->operations); + +#if 1 + if (was_entered(*it, *iit, first, ls1, ls2)) + { + detail::overlay::debug_traverse(*it, *iit, "-> Was entered"); + entered = true; + } +#endif + + if (is_staying_inside(*it, *iit, entered, first, ls1, ls2)) + { + detail::overlay::debug_traverse(*it, *iit, "-> Staying inside"); + + entered = true; + } + else if (/*!entered &&*/ is_entering(*it, *iit, ls1, ls2)) + { + detail::overlay::debug_traverse(*it, *iit, "-> Entering"); + + entered = true; + action::enter(current_piece, linestring1, current_segment_id, iit->seg_id.segment_index, it->point, *iit, oit); + } + else if (is_leaving(*it, *iit, entered, first, ls1, ls2)) + { + detail::overlay::debug_traverse(*it, *iit, "-> Leaving"); + + entered = false; + action::leave(current_piece, linestring1, current_segment_id, iit->seg_id.segment_index, it->point, *iit, oit); + } + first = false; + } + +#if 1 + if (action::is_entered(entered)) + { + geometry::copy_segments(ls1, current_segment_id, + boost::size(linestring1) - 1, + current_piece); + } + + // Output the last one, if applicable + if (::boost::size(current_piece) > 1) + { + *oit++ = current_piece; + } +#endif +#endif + return oit; + } +}; + + + + +}} // namespace detail::difference +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIFFERENCE_LINEAR_LINEAR_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index b906ca4ec..ba8ca15c3 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -2,10 +2,15 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP @@ -32,6 +37,9 @@ #include +#include + + #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) #include #endif @@ -505,6 +513,44 @@ struct intersection_insert_reversed }; +template +< + typename LineString1, typename LineString2, + typename LineStringOut, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + LineString1, LineString2, + LineStringOut, + overlay_difference, + Reverse1, Reverse2, ReverseOut, + linestring_tag, linestring_tag, linestring_tag, + false, false, false + > : detail::difference::linestring_linestring_linestring +{}; + + +template +< + typename MultiLineString1, typename MultiLineString2, + typename LineStringOut, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + MultiLineString1, MultiLineString2, + LineStringOut, + overlay_difference, + Reverse1, Reverse2, ReverseOut, + multi_linestring_tag, multi_linestring_tag, linestring_tag, + false, false, false + > : detail::difference::multilinestring_multilinestring_linestring +{}; + + + + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index 67d3763ea..405d8cadc 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -85,10 +85,10 @@ struct get_turns dispatch::get_turns < - typename bg::tag::type, typename bg::tag::type, + typename tag::type, typename tag::type, Geometry1, Geometry2, reverse1, reverse2, GetTurnPolicy - >::apply(0, geometry1, 1, geometry2, bg::detail::no_rescale_policy(), turns, interrupt_policy); + >::apply(0, geometry1, 1, geometry2, detail::no_rescale_policy(), turns, interrupt_policy); } }; diff --git a/include/boost/geometry/algorithms/detail/turns/print_turns.hpp b/include/boost/geometry/algorithms/detail/turns/print_turns.hpp index e9e3b6690..dd6aa62b5 100644 --- a/include/boost/geometry/algorithms/detail/turns/print_turns.hpp +++ b/include/boost/geometry/algorithms/detail/turns/print_turns.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace boost { namespace geometry { diff --git a/test/algorithms/difference1.cpp b/test/algorithms/difference1.cpp index a9e8dac17..ea7bc525f 100644 --- a/test/algorithms/difference1.cpp +++ b/test/algorithms/difference1.cpp @@ -1,3 +1,12 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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 + #include #ifndef BOOST_TEST_MODULE @@ -10,7 +19,7 @@ #include #include -#include "/home/mkaravel/bg/boost/geometry/mysql/algorithms/difference.hpp" +#include typedef bg::model::point point_type; typedef bg::model::segment segment_type; diff --git a/test/algorithms/test_difference1.hpp b/test/algorithms/test_difference1.hpp index fcdc12aa2..04fcb2a51 100644 --- a/test/algorithms/test_difference1.hpp +++ b/test/algorithms/test_difference1.hpp @@ -1,3 +1,12 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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_GEOMETRY_TEST_DIFFERENCE1_HPP #define BOOST_GEOMETRY_TEST_DIFFERENCE1_HPP