From be1ac99a822b3db32097c7f37bc6bdcecbfe2dbd Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Feb 2014 18:59:30 +0100 Subject: [PATCH] get_turns(L,A) added, the endpoints are NOT properly set yet! --- .../detail/overlay/get_turn_info_la.hpp | 326 ++++++++++++++++++ .../algorithms/detail/overlay/get_turns.hpp | 19 +- .../overlay/get_turns_linear_areal.cpp | 4 +- 3 files changed, 338 insertions(+), 11 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp new file mode 100644 index 000000000..171cdb507 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -0,0 +1,326 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013-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 Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP + +#include +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay { + +template +struct get_turn_info_linear_areal +{ + template + < + typename Point1, + typename Point2, + typename TurnInfo, + typename RescalePolicy, + typename OutputIterator + > + static inline OutputIterator apply( + Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, +// TODO: should this always be std::size_t or replace with template parameter? + std::size_t p_segments_count, + std::size_t q_segments_count, + TurnInfo const& tp_model, + RescalePolicy const& , // TODO: this will be used. rescale_policy, + OutputIterator out) + { + typedef model::referring_segment segment_type1; + typedef model::referring_segment segment_type2; + segment_type1 p1(pi, pj), p2(pj, pk); + segment_type2 q1(qi, qj), q2(qj, qk); + + side_calculator side_calc(pi, pj, pk, qi, qj, qk); + + typedef strategy_intersection + < + typename cs_tag::type, + Point1, + Point2, + typename TurnInfo::point_type + > si; + + typedef typename si::segment_intersection_strategy_type strategy; + + typename strategy::return_type result = strategy::apply(p1, q1); + + char const method = result.template get<1>().how; + + // Copy, to copy possibly extended fields + TurnInfo tp = tp_model; + + // Select method and apply + switch(method) + { + case 'a' : // collinear, "at" + case 'f' : // collinear, "from" + case 's' : // starts from the middle + /*get_turn_info_for_endpoint + ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + tp_model, result, method_none, out);*/ + break; + + case 'd' : // disjoint: never do anything + break; + + case 'm' : + { + //if ( get_turn_info_for_endpoint + // ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + // tp_model, result, method_touch_interior, out) ) + //{ + // // do nothing + //} + //else + { + typedef touch_interior + < + TurnInfo + > policy; + + // If Q (1) arrives (1) + if (result.template get<1>().arrival[1] == 1) + { + policy::template apply<0>(pi, pj, pk, qi, qj, qk, + tp, result.template get<0>(), result.template get<1>(), + side_calc); + } + else + { + // Swap p/q + side_calculator swapped_side_calc(qi, qj, qk, pi, pj, pk); + policy::template apply<1>(qi, qj, qk, pi, pj, pk, + tp, result.template get<0>(), result.template get<1>(), + swapped_side_calc); + } + + replace_method_and_operations_tm(tp.method, tp.operations[0].operation, tp.operations[1].operation); + + AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + *out++ = tp; + } + } + break; + case 'i' : + { + crosses::apply(pi, pj, pk, qi, qj, qk, + tp, result.template get<0>(), result.template get<1>()); + + replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); + + AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + *out++ = tp; + } + break; + case 't' : + { + // Both touch (both arrive there) + //if ( get_turn_info_for_endpoint + // ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + // tp_model, result, method_touch, out) ) + //{ + // // do nothing + //} + //else + { + touch::apply(pi, pj, pk, qi, qj, qk, + tp, result.template get<0>(), result.template get<1>(), side_calc); + + replace_method_and_operations_tm(tp.method, tp.operations[0].operation, tp.operations[1].operation); + + AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + *out++ = tp; + } + } + break; + case 'e': + { + /*if ( get_turn_info_for_endpoint + ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + tp_model, result, method_equal, out) ) + { + // do nothing + } + else */if ( ! result.template get<1>().opposite ) + { + // Both equal + // or collinear-and-ending at intersection point + equal::apply(pi, pj, pk, qi, qj, qk, + tp, result.template get<0>(), result.template get<1>(), side_calc); + + replacer_of_method_and_operations_ec replacer(method_touch); + replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); + + AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + *out++ = tp; + } + else + { + equal_opposite + < + TurnInfo, + AssignPolicy + >::apply(pi, qi, + tp, out, result.template get<0>(), result.template get<1>()); + } + } + break; + case 'c' : + { + // Collinear + /*if ( get_turn_info_for_endpoint + ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + tp_model, result, method_collinear, out) ) + { + // do nothing + } + else*/ if (! result.template get<1>().opposite) + { + + if (result.template get<1>().arrival[0] == 0) + { + // Collinear, but similar thus handled as equal + equal::apply(pi, pj, pk, qi, qj, qk, + tp, result.template get<0>(), result.template get<1>(), side_calc); + + // NOTE: don't change the method only if methods are WRT IPs, not segments! + // (currently this approach is used) + // override assigned method + //tp.method = method_collinear; + + replacer_of_method_and_operations_ec replacer(method_touch); + replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); + } + else + { + collinear::apply(pi, pj, pk, qi, qj, qk, + tp, result.template get<0>(), result.template get<1>(), side_calc); + + replacer_of_method_and_operations_ec replacer(method_touch_interior); + replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); + } + + AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + *out++ = tp; + } + else + { + // If this always 'm' ? + replacer_of_method_and_operations_ec replacer(method_touch_interior); + + collinear_opposite + < + TurnInfo, + AssignPolicy + >::apply(pi, pj, pk, qi, qj, qk, + tp, out, result.template get<0>(), result.template get<1>(), side_calc, + replacer); + } + } + break; + case '0' : + { + // degenerate points + if (AssignPolicy::include_degenerate) + { + only_convert::apply(tp, result.template get<0>()); + AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + *out++ = tp; + } + } + break; + default : + { +#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS) + std::cout << "TURN: Unknown method: " << method << std::endl; +#endif +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + throw turn_info_exception(method); +#endif + } + break; + } + + return out; + } + + static inline void replace_method_and_operations_tm(method_type & method, + operation_type & op0, + operation_type & op1) + { + if ( op0 == operation_blocked && op1 == operation_blocked ) + { + // NOTE: probably only if methods are WRT IPs, not segments! + method = (method == method_touch ? method_equal : method_collinear); + } + + // assuming Linear is always the first one + if ( op0 == operation_blocked ) + op0 = operation_continue; + + op1 = operation_union; + } + + class replacer_of_method_and_operations_ec + { + public: + explicit replacer_of_method_and_operations_ec(method_type method_t_or_m) + : m_method(method_t_or_m) + {} + + void operator()(method_type & method, + operation_type & op0, + operation_type & op1) const + { + // assuming Linear is always the first one + if ( op0 == operation_blocked ) + op0 = operation_continue; + + if ( op1 != operation_continue ) + op1 = operation_union; + + // NOTE: probably only if methods are WRT IPs, not segments! + if ( op0 == operation_intersection || op0 == operation_union + || op1 == operation_intersection || op1 == operation_union ) + { + method = m_method; + } + } + + private: + method_type m_method; + }; + + static inline void replace_operations_i(operation_type & op0, operation_type & op1) + { + // assuming Linear is always the first one + op1 = operation_union; + } + + +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 40f8e6f2c..4e6af9ba1 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -53,6 +53,7 @@ #include #include #include +#include #include @@ -766,10 +767,10 @@ struct get_turn_info_type {}; -//template -//struct get_turn_info_type -// : overlay::get_turn_info_linear_linear -//{}; +template +struct get_turn_info_type + : overlay::get_turn_info_linear_areal +{}; template ::type, typename Tag2 = typename tag::type, @@ -785,11 +786,11 @@ struct turn_operation_type -//struct turn_operation_type -//{ -// typedef overlay::turn_operation_linear type; -//}; +template +struct turn_operation_type +{ + typedef overlay::turn_operation_linear type; +}; }} // namespace detail::get_turns #endif // DOXYGEN_NO_DETAIL diff --git a/test/algorithms/overlay/get_turns_linear_areal.cpp b/test/algorithms/overlay/get_turns_linear_areal.cpp index 10334260f..69ec207ed 100644 --- a/test/algorithms/overlay/get_turns_linear_areal.cpp +++ b/test/algorithms/overlay/get_turns_linear_areal.cpp @@ -32,11 +32,11 @@ void test_all() typedef bg::model::linestring ls; typedef bg::model::polygon poly; - to_svg("LINESTRING(15 5,24 5,20 2,19 0,13 -4,10 0,13 3,15 7,16 10,10 10,8 10,4 6,2 8,1 10)", + to_svg("LINESTRING(15 5,24 5,20 2,19 0,13 -4,1 0,10 0,13 3,15 7,16 10,10 10,8 10,4 6,2 8,1 10)", "POLYGON((0 0,5 5,0 10,20 10,20 2,19 0,0 0)(10 3,15 3,15 7,10 7,10 3))", "ls_poly.svg"); to_svg("POLYGON((0 0,5 5,0 10,20 10,20 2,19 0,0 0)(10 3,15 3,15 7,10 7,10 3))", - "LINESTRING(15 5,24 5,20 2,19 0,13 -4,10 0,13 3,15 7,16 10,10 10,8 10,4 6,2 8,1 10)", + "LINESTRING(15 5,24 5,20 2,19 0,13 -4,1 0,10 0,13 3,15 7,16 10,10 10,8 10,4 6,2 8,1 10)", "poly_ls.svg"); }