mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 13:34:10 +00:00
[buffer][fix] use taxicab distance instead of comparable distance
This is faster and avoids overflows. This fixes rt_u6
This commit is contained in:
parent
31abd20829
commit
a7764c1b9e
@ -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
|
||||
|
@ -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* [])
|
||||
|
Loading…
x
Reference in New Issue
Block a user