Skip to content

Commit 0ee3d33

Browse files
committed
[test] add unit test for get_distance_measure showing its failures
1 parent eb879fe commit 0ee3d33

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

test/algorithms/overlay/Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ test-suite boost-geometry-algorithms-overlay
1818
[ run assemble.cpp : : : : algorithms_assemble ]
1919
[ run copy_segment_point.cpp : : : : algorithms_copy_segment_point ]
2020
[ run get_clusters.cpp : : : : algorithms_get_clusters ]
21+
[ run get_distance_measure.cpp : : : : algorithms_get_distance_measure ]
2122
[ run get_ring.cpp : : : : algorithms_get_ring ]
2223
[ run get_turn_info.cpp : : : : algorithms_get_turn_info ]
2324
[ run get_turns.cpp : : : : algorithms_get_turns ]
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Boost.Geometry
2+
// Unit Test
3+
4+
// Copyright (c) 2023 Barend Gehrels, Amsterdam, the Netherlands.
5+
6+
// Use, modification and distribution is subject to the Boost Software License,
7+
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8+
// http://www.boost.org/LICENSE_1_0.txt)
9+
10+
#include <geometry_test_common.hpp>
11+
12+
#include <boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp>
13+
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
14+
#include <boost/geometry/strategies/strategies.hpp>
15+
#include <boost/geometry/geometries/geometries.hpp>
16+
#include <boost/geometry/io/wkt/wkt.hpp>
17+
18+
// #define BOOST_GEOMETRY_TEST_WITH_COUT
19+
// #define BOOST_GEOMETRY_TEST_FAILURES
20+
21+
template <typename Point>
22+
void do_test(std::string const& case_id,
23+
Point const& s1,
24+
Point const& s2,
25+
Point const& p,
26+
int expected_side,
27+
bool ignore_failure = false)
28+
{
29+
using coor_t = typename bg::coordinate_type<Point>::type;
30+
typename bg::strategies::relate::services::default_strategy
31+
<
32+
Point, Point
33+
>::type strategy;
34+
35+
auto const dm = bg::detail::get_distance_measure(s1, s2, p, strategy);
36+
auto const dm_side = dm.measure < 0.0 ? -1 : dm.measure > 0.0 ? 1 : 0;
37+
auto const tr_side = strategy.side().apply(s1, s2, p);
38+
auto const rob_side = bg::strategy::side::side_robust<coor_t>::apply(s1, s2, p);
39+
40+
#if defined(BOOST_GEOMETRY_TEST_WITH_COUT)
41+
std::cout << " " << case_id << " " << string_from_type<coor_t>::name()
42+
<< std::setprecision(20)
43+
<< " " << dm.measure << " " << dm_side << " " << tr_side << " " << rob_side
44+
<< (dm_side != rob_side ? " [*** DM WRONG]" : "")
45+
<< (tr_side != rob_side ? " [*** TR WRONG]" : "")
46+
<< std::endl;
47+
#endif
48+
49+
BOOST_CHECK_MESSAGE(expected_side == -9 || expected_side == dm_side,
50+
"Case: " << case_id
51+
<< " ctype: " << string_from_type<coor_t>::name()
52+
<< " expected: " << expected_side
53+
<< " detected: " << dm_side);
54+
55+
// This is often wrong for float, and sometimes for double
56+
BOOST_CHECK_MESSAGE(ignore_failure || tr_side == dm_side,
57+
"Case: " << case_id
58+
<< " ctype: " << string_from_type<coor_t>::name()
59+
<< " tr_side: " << tr_side
60+
<< " dm_side: " << dm_side);
61+
62+
// This is always guaranteed for the tested values
63+
BOOST_CHECK_MESSAGE(tr_side == rob_side,
64+
"Case: " << case_id
65+
<< " ctype: " << string_from_type<coor_t>::name()
66+
<< " tr_side: " << tr_side
67+
<< " rob_side: " << rob_side);
68+
}
69+
70+
template <typename Point>
71+
void test_get_distance_measure()
72+
{
73+
using coor_t = typename bg::coordinate_type<Point>::type;
74+
75+
do_test<Point>("simplex_coll", {1.0, 0.0}, {1.0, 1.0}, {1.0, 0.5}, 0);
76+
do_test<Point>("simplex_left", {1.0, 0.0}, {1.0, 1.0}, {0.9, 0.5}, 1);
77+
do_test<Point>("simplex_right", {1.0, 0.0}, {1.0, 1.0}, {1.1, 0.5}, -1);
78+
79+
bool const is_float = std::is_same<coor_t, float>::value;
80+
bool const is_double = std::is_same<coor_t, double>::value;
81+
82+
// The issue 1183 where get_distance_measure failed for these coordinates.
83+
std::string const case_id = "issue_1183_";
84+
Point const p1{38902.349206128216, 6721371.1493254723};
85+
Point const p2{38937.993505971914, 6721407.9151819283};
86+
Point const q1 = p1;
87+
Point const q2{38960.647313876834, 6721431.2817974398};
88+
{
89+
do_test<Point>(case_id + "p", p1, p2, q2, 1, is_float);
90+
do_test<Point>(case_id + "q", q1, q2, p1, 0);
91+
}
92+
93+
double const test_epsilon = 1.0e-9;
94+
95+
// Walk along x axis to get the switch from left to right (between 2 and 3)
96+
for (int i = -5; i <= 15; i++)
97+
{
98+
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
99+
bool const ignore_failure = false;
100+
#else
101+
bool const ignore_failure = is_float || (is_double && i >= 3 && i <= 12);
102+
#endif
103+
double const v = i / 10.0;
104+
Point q2a = q2;
105+
bg::set<0>(q2a, bg::get<0>(q2) + v * test_epsilon);
106+
do_test<Point>(case_id + std::to_string(i), p1, p2, q2a, -9, ignore_failure);
107+
}
108+
// Focus on the switch from left to right (between 0.251 and 0.252)
109+
for (int i = 250; i <= 260; i++)
110+
{
111+
double const v = i / 1000.0;
112+
Point q2a = q2;
113+
bg::set<0>(q2a, bg::get<0>(q2) + v * test_epsilon);
114+
do_test<Point>(case_id + std::to_string(i), p1, p2, q2, -9, is_float || is_double);
115+
}
116+
}
117+
118+
int test_main(int, char* [])
119+
{
120+
using fp = bg::model::point<float, 2, bg::cs::cartesian>;
121+
using dp = bg::model::point<double, 2, bg::cs::cartesian>;
122+
using ep = bg::model::point<long double, 2, bg::cs::cartesian>;
123+
124+
test_get_distance_measure<fp>();
125+
test_get_distance_measure<dp>();
126+
test_get_distance_measure<ep>();
127+
128+
return 0;
129+
}

0 commit comments

Comments
 (0)