mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-10 23:42:12 +00:00
get_turns(L,A) added, the endpoints are NOT properly set yet!
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user