[buffer][fix] use taxicab distance instead of comparable distance

This is faster and avoids overflows. This fixes rt_u6
This commit is contained in:
Barend Gehrels 2014-08-10 15:32:07 +02:00
parent 31abd20829
commit a7764c1b9e
2 changed files with 32 additions and 13 deletions

View File

@ -56,6 +56,8 @@ class turn_in_piece_visitor
Turns& m_turns; // because partition is currently operating on const input only
Pieces const& m_pieces; // to check for piece-type
typedef boost::long_long_type calculation_type;
template <typename Point>
static inline bool projection_on_segment(Point const& subject, Point const& p, Point const& q)
{
@ -83,9 +85,17 @@ class turn_in_piece_visitor
return true;
}
template <typename Point>
static inline calculation_type taxicab_distance(Point const& p, Point const& q)
{
return math::abs(geometry::get<0>(p) - geometry::get<0>(q))
+ math::abs(geometry::get<1>(p) - geometry::get<1>(q));
}
// TODO: see comment below, this adaption of distance_projected_point can be removed
template <typename Point>
static inline boost::long_long_type distance_from_segment(Point const& subject, Point const& p, Point const& q)
static inline calculation_type taxicab_distance_from_segment(Point const& subject, Point const& p, Point const& q)
{
typedef Point vector_type;
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
@ -98,15 +108,14 @@ class turn_in_piece_visitor
coordinate_type const zero = coordinate_type();
coordinate_type const c1 = dot_product(w, v);
if (c1 < zero)
if (c1 <= zero)
{
// Any value above 2 is fine in this case
return 99999;
return taxicab_distance(subject, p);
}
coordinate_type const c2 = dot_product(v, v);
if (c2 < c1 || c2 <= zero)
if (c2 <= c1)
{
return 99999;
return taxicab_distance(subject, q);
}
multiply_value(v, c1);
@ -118,7 +127,9 @@ class turn_in_piece_visitor
add_point(projected, v);
return dot_product(subject, projected);
// The dot-product still overflows for boost::long_long_type with
// these values (should not occur, TODO: fix this)
return taxicab_distance(subject, projected);
}
@ -148,17 +159,18 @@ class turn_in_piece_visitor
}
template <typename Point, typename Piece>
inline boost::long_long_type
comparable_distance_from_offsetted(Point const& point, Piece const& piece) const
inline calculation_type
taxicab_distance_from_offsetted(Point const& point, Piece const& piece) const
{
// TODO: replace this by the code below if that is fixed for boost::long_long_type
// with these contents of values
boost::long_long_type result = 0;
calculation_type result = 0;
for (int i = 1; i < piece.offsetted_count; i++)
{
Point const& previous = piece.robust_ring[i - 1];
Point const& current = piece.robust_ring[i];
boost::long_long_type dist = distance_from_segment(point, previous, current);
calculation_type const dist
= taxicab_distance_from_segment(point, previous, current);
if (i == 1 || dist < result)
{
result = dist;
@ -258,9 +270,11 @@ public:
if (geometry_code == 1)
{
if (comparable_distance_from_offsetted(turn.robust_point, piece) >= 2)
calculation_type const distance
= taxicab_distance_from_offsetted(turn.robust_point, piece);
if (distance >= 2)
{
// This is too far from the border, it counts as really inside
// This is too far from the border, it counts as "really within"
mutable_turn.count_within++;
}
else

View File

@ -233,6 +233,10 @@ static std::string const rt_u4
static std::string const rt_u5
= "MULTIPOLYGON(((4 3,4 4,5 4,5 3,4 3)),((6 5,6 6,7 6,6 5)),((5 4,6 5,6 4,5 4)),((4 0,4 1,5 1,5 0,4 0)),((7 8,8 9,8 8,7 8)),((8 2,8 3,9 3,8 2)),((2 1,2 2,3 1,2 1)),((5 7,5 8,6 8,5 7)),((4 5,4 6,5 5,4 5)),((7 0,8 1,8 0,7 0)),((7 2,8 1,7 1,6 1,7 2)),((3 3,4 3,4 2,3 2,3 3)),((3 9,3 10,4 9,3 9)),((1 2,2 3,2 2,1 2)),((2 4,2 5,3 4,2 3,2 4)),((3 7,4 7,3 6,2 6,3 7)))";
static std::string const rt_u6
= "MULTIPOLYGON(((2 2,3 3,3 2,2 2)),((9 8,9 9,10 9,10 8,9 8)),((5 3,6 4,6 3,5 3)),((5 5,5 6,6 6,5 5)),((5 1,6 2,6 1,5 1)),((6 5,7 6,7 5,6 5)),((3 0,4 1,4 0,3 0)),((6 6,6 7,7 6,6 6)),((9 2,10 2,10 1,9 1,9 2)),((6 8,6 9,7 9,7 8,6 8)),((7 0,7 1,8 0,7 0)),((4 4,4 5,5 5,4 4)),((0 7,0 8,1 8,0 7)),((5 9,6 10,6 9,5 9)),((4 9,4 10,5 10,5 9,4 9)),((3 7,4 7,3 6,2 6,3 7)),((9 7,10 6,9 6,8 6,9 7)),((5 3,5 2,4 2,4 3,4 4,5 4,5 3)),((1 1,2 0,1 0,0 0,1 1)),((2 10,3 10,3 9,2 9,1 9,1 10,2 10)),((8.5 4.5,9 4,8 4,7 4,8 5,9 5,8.5 4.5)),((8 3,9 3,9 2,8 2,8 3)))";
template <typename P>
void test_all()
@ -348,6 +352,7 @@ void test_all()
test_one<multi_polygon_type, polygon_type>("rt_u3", rt_u3, join_round, end_flat, 133.4526, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u4", rt_u4, join_round, end_flat, 126.9268, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u5", rt_u5, join_round, end_flat, 78.4906, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u6", rt_u6, join_round, end_flat, 115.4461, 1.0);
}
int test_main(int, char* [])