[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 typename SidePolicy
> >
static inline void apply( static inline void apply(
Point1 const& , Point1 const& , Point1 const& , Point1 const& , Point1 const& pj, Point1 const& pk,
Point2 const& , Point2 const& , Point2 const& , Point2 const& , Point2 const& qj, Point2 const& qk,
TurnInfo& ti, TurnInfo& ti,
IntersectionInfo const& info, IntersectionInfo const& info,
DirInfo const& dir_info, DirInfo const& dir_info,
@ -623,8 +623,30 @@ struct collinear : public base_turn_handler
{ {
ui_else_iu(product == 1, ti); 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 template

View File

@ -23,9 +23,9 @@ namespace detail { namespace overlay {
enum turn_position { position_middle, position_front, position_back }; enum turn_position { position_middle, position_front, position_back };
template <typename SegmentRatio> template <typename Point, typename SegmentRatio>
struct turn_operation_linear struct turn_operation_linear
: public turn_operation<SegmentRatio> : public turn_operation<Point, SegmentRatio>
{ {
turn_operation_linear() turn_operation_linear()
: position(position_middle) : 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> typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>
struct turn_operation_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> template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, linear_tag> 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> template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, areal_tag> 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 }} // namespace detail::get_turns

View File

@ -25,7 +25,7 @@ namespace detail { namespace overlay
template <typename Point, typename SegmentRatio> 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; enrichment_info<Point> enriched;
visit_info visited; visit_info visited;

View File

@ -174,7 +174,17 @@ inline bool select_next_ip(operation_type operation,
{ {
return false; return false;
} }
bool has_tp = 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); selected = boost::end(turn.operations);
for (Iterator it = boost::begin(turn.operations); for (Iterator it = boost::begin(turn.operations);
it != boost::end(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; selected = it;
debug_traverse(turn, *it, " Candidate"); debug_traverse(turn, *it, " Candidate");
has_tp = true; 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) if (has_tp)

View File

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

View File

@ -44,7 +44,7 @@
// To test that "get_turns" can be called using additional information // To test that "get_turns" can be called using additional information
template <typename Point, typename SegmentRatio> 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, 1,
0, 0,
-1, -1,
313.36036462, 0.01); 313.36036462, 0.1);
// SQL Server gives: 313.360374193241 // SQL Server gives: 313.360374193241
// PostGIS gives: 313.360364623393 // PostGIS gives: 313.360364623393
@ -319,10 +319,8 @@ void test_areal()
1, 0, if_typed<ct, double>(18, 23), 4.60853); 1, 0, if_typed<ct, double>(18, 23), 4.60853);
#endif #endif
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<Polygon, Polygon, Polygon>("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], 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); 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], 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); 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], 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); 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], test_one<Polygon, Polygon, Polygon>("buffer_rt_q", buffer_rt_q[0], buffer_rt_q[1],
1, 0, 18, 18.5710); 1, 0, 18, 18.5710);
#endif
test_one<Polygon, Polygon, Polygon>("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0], test_one<Polygon, Polygon, Polygon>("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0],
1, 0, 18, 18.5710); 1, 0, 18, 18.5710);