get_turns(L,A) added, the endpoints are NOT properly set yet!

This commit is contained in:
Adam Wulkiewicz
2014-02-28 18:59:30 +01:00
parent ad201710c7
commit be1ac99a82
3 changed files with 338 additions and 11 deletions

View File

@@ -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 <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay {
template<typename AssignPolicy>
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<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
segment_type1 p1(pi, pj), p2(pj, pk);
segment_type2 q1(qi, qj), q2(qj, qk);
side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
typedef strategy_intersection
<
typename cs_tag<typename TurnInfo::point_type>::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<AssignPolicy, true, true>
::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<AssignPolicy, false, true>
// ::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<Point1, Point2> 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<TurnInfo>::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<AssignPolicy, false, true>
// ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
// tp_model, result, method_touch, out) )
//{
// // do nothing
//}
//else
{
touch<TurnInfo>::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<AssignPolicy, true, true>
::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<TurnInfo>::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<AssignPolicy, true, true>
::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<TurnInfo>::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<TurnInfo>::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<TurnInfo>::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

View File

@@ -53,6 +53,7 @@
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
@@ -766,10 +767,10 @@ struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear
: overlay::get_turn_info_linear_linear<AssignPolicy>
{};
//template <typename Geometry1, typename Geometry2, typename AssignPolicy, typename Tag1, typename Tag2>
//struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear_tag, areal_tag>
// : overlay::get_turn_info_linear_linear<AssignPolicy>
//{};
template <typename Geometry1, typename Geometry2, typename AssignPolicy, typename Tag1, typename Tag2>
struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear_tag, areal_tag>
: overlay::get_turn_info_linear_areal<AssignPolicy>
{};
template <typename Geometry1, typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type,
@@ -785,11 +786,11 @@ struct turn_operation_type<Geometry1, Geometry2, Tag1, Tag2, linear_tag, linear_
typedef overlay::turn_operation_linear type;
};
//template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
//struct turn_operation_type<Geometry1, Geometry2, Tag1, Tag2, linear_tag, areal_tag>
//{
// typedef overlay::turn_operation_linear type;
//};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
struct turn_operation_type<Geometry1, Geometry2, Tag1, Tag2, linear_tag, areal_tag>
{
typedef overlay::turn_operation_linear type;
};
}} // namespace detail::get_turns
#endif // DOXYGEN_NO_DETAIL

View File

@@ -32,11 +32,11 @@ void test_all()
typedef bg::model::linestring<pt> ls;
typedef bg::model::polygon<pt> poly;
to_svg<ls, poly>("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<ls, poly>("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<poly, ls>("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");
}