[traverse][robustness] in case of cc, instead of arbitrary candidate,

take candidate with largest remaining distance. This fixes some
errors if rescaling is turned off.
This commit is contained in:
Barend Gehrels 2015-10-14 17:15:53 +02:00
parent 74f5465516
commit 533543e86b
9 changed files with 65 additions and 18 deletions

View File

@ -585,8 +585,8 @@ struct collinear : public base_turn_handler
typename SidePolicy
>
static inline void apply(
Point1 const& , Point1 const& , Point1 const& ,
Point2 const& , Point2 const& , Point2 const& ,
Point1 const& , Point1 const& pj, Point1 const& pk,
Point2 const& , Point2 const& qj, Point2 const& qk,
TurnInfo& ti,
IntersectionInfo const& info,
DirInfo const& dir_info,
@ -623,8 +623,30 @@ struct collinear : public base_turn_handler
{
ui_else_iu(product == 1, ti);
}
// Calculate remaining distance. If it continues collinearly it is
// measured until the end of the next segment
ti.operations[0].remaining_distance
= side_p == 0
? distance_measure(ti.point, pk)
: distance_measure(ti.point, pj);
ti.operations[1].remaining_distance
= side_q == 0
? distance_measure(ti.point, qk)
: distance_measure(ti.point, qj);
}
template <typename Point1, typename Point2>
static inline typename geometry::coordinate_type<Point1>::type
distance_measure(Point1 const& a, Point2 const& b)
{
// TODO: use comparable distance for point-point instead - but that
// causes currently cycling include problems
typedef typename geometry::coordinate_type<Point1>::type ctype;
ctype const dx = get<0>(a) - get<0>(b);
ctype const dy = get<1>(b) - get<1>(b);
return dx * dx + dy * dy;
}
};
template

View File

@ -23,9 +23,9 @@ namespace detail { namespace overlay {
enum turn_position { position_middle, position_front, position_back };
template <typename SegmentRatio>
template <typename Point, typename SegmentRatio>
struct turn_operation_linear
: public turn_operation<SegmentRatio>
: public turn_operation<Point, SegmentRatio>
{
turn_operation_linear()
: position(position_middle)

View File

@ -802,19 +802,19 @@ template <typename Geometry1, typename Geometry2, typename SegmentRatio,
typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>
struct turn_operation_type
{
typedef overlay::turn_operation<SegmentRatio> type;
typedef overlay::turn_operation<typename point_type<Geometry1>::type, SegmentRatio> type;
};
template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, linear_tag>
{
typedef overlay::turn_operation_linear<SegmentRatio> type;
typedef overlay::turn_operation_linear<typename point_type<Geometry1>::type, SegmentRatio> type;
};
template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, areal_tag>
{
typedef overlay::turn_operation_linear<SegmentRatio> type;
typedef overlay::turn_operation_linear<typename point_type<Geometry1>::type, SegmentRatio> type;
};
}} // namespace detail::get_turns

View File

@ -25,7 +25,7 @@ namespace detail { namespace overlay
template <typename Point, typename SegmentRatio>
struct traversal_turn_operation : public turn_operation<SegmentRatio>
struct traversal_turn_operation : public turn_operation<Point, SegmentRatio>
{
enrichment_info<Point> enriched;
visit_info visited;

View File

@ -174,7 +174,17 @@ inline bool select_next_ip(operation_type operation,
{
return false;
}
bool has_tp = false;
typedef typename std::iterator_traits
<
Iterator
>::value_type operation_type;
typename operation_type::comparable_distance_type
max_remaining_distance = 0;
selected = boost::end(turn.operations);
for (Iterator it = boost::begin(turn.operations);
it != boost::end(turn.operations);
@ -206,10 +216,24 @@ inline bool select_next_ip(operation_type operation,
)
)
{
if (it->operation == operation_continue)
{
max_remaining_distance = it->remaining_distance;
}
selected = it;
debug_traverse(turn, *it, " Candidate");
has_tp = true;
}
if (it->operation == operation_continue && has_tp)
{
if (it->remaining_distance > max_remaining_distance)
{
max_remaining_distance = it->remaining_distance;
selected = it;
debug_traverse(turn, *it, " Candidate override");
}
}
}
if (has_tp)

View File

@ -12,6 +12,7 @@
#include <boost/array.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
namespace boost { namespace geometry
@ -54,15 +55,19 @@ enum method_type
The class is to be included in the turn_info class, either direct
or a derived or similar class with more (e.g. enrichment) information.
*/
template <typename SegmentRatio>
template <typename Point, typename SegmentRatio>
struct turn_operation
{
operation_type operation;
segment_identifier seg_id;
SegmentRatio fraction;
typedef typename coordinate_type<Point>::type comparable_distance_type;
comparable_distance_type remaining_distance;
inline turn_operation()
: operation(operation_none)
, remaining_distance(0)
{}
};
@ -80,7 +85,7 @@ template
<
typename Point,
typename SegmentRatio,
typename Operation = turn_operation<SegmentRatio>,
typename Operation = turn_operation<Point, SegmentRatio>,
typename Container = boost::array<Operation, 2>
>
struct turn_info

View File

@ -128,8 +128,8 @@ struct get_turns
template <int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0>
struct op_to_int
{
template <typename SegmentRatio>
inline int operator()(detail::overlay::turn_operation<SegmentRatio> const& op) const
template <typename Operation>
inline int operator()(Operation const& op) const
{
switch(op.operation)
{

View File

@ -44,7 +44,7 @@
// To test that "get_turns" can be called using additional information
template <typename Point, typename SegmentRatio>
struct my_turn_op : public bg::detail::overlay::turn_operation<SegmentRatio>
struct my_turn_op : public bg::detail::overlay::turn_operation<Point, SegmentRatio>
{
};

View File

@ -248,7 +248,7 @@ void test_areal()
1,
0,
-1,
313.36036462, 0.01);
313.36036462, 0.1);
// SQL Server gives: 313.360374193241
// PostGIS gives: 313.360364623393
@ -319,10 +319,8 @@ void test_areal()
1, 0, if_typed<ct, double>(18, 23), 4.60853);
#endif
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<Polygon, Polygon, Polygon>("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1],
1, 0, if_typed<ct, float>(18, 17), 16.571);
#endif
test_one<Polygon, Polygon, Polygon>("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0],
1, 0, if_typed<ct, float>(18, 17), 16.571);
@ -355,10 +353,8 @@ void test_areal()
test_one<Polygon, Polygon, Polygon>("buffer_rt_m2_rev", buffer_rt_m2[1], buffer_rt_m2[0],
1, 0, if_typed_tt<ct>(20, 19), 21.4853);
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<Polygon, Polygon, Polygon>("buffer_rt_q", buffer_rt_q[0], buffer_rt_q[1],
1, 0, 18, 18.5710);
#endif
test_one<Polygon, Polygon, Polygon>("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0],
1, 0, 18, 18.5710);