Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[overlay] fix cluster by adapting tolerance #1093

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/release_notes.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
[*Solved issues]

* [@https://github.com/boostorg/geometry/issues/1076 1076] Union: in rare cases it might miss one polygon
* [@https://github.com/boostorg/geometry/issues/1081 1081] Union: due to precision it might miss interior rings
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vissarion if this will not make it in 1.81 then I will update the PR (later)


[/=================]
[heading Boost 1.80]
Expand Down
17 changes: 13 additions & 4 deletions include/boost/geometry/algorithms/detail/overlay/get_clusters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,29 @@ namespace detail { namespace overlay
template <typename Tag = no_rescale_policy_tag, bool Integral = false>
struct sweep_equal_policy
{
private:
template <typename T>
static inline T threshold()
{
// Tuned by cases of #1081. It should just be one epsilon to distinguish between
// different turn-points and real colocated clusters.
return T(1);
}
public:
// Returns true if point are considered equal (within an epsilon)
template <typename P>
static inline bool equals(P const& p1, P const& p2)
{
// Points within a kilo epsilon are considered as equal
using coor_t = typename coordinate_type<P>::type;
return approximately_equals(p1, p2, coor_t(1000));
return approximately_equals(p1, p2, threshold<coor_t>());
}

template <typename T>
static inline bool exceeds(T value)
{
// This threshold is an arbitrary value
// as long as it is than the used kilo-epsilon
T const limit = T(1) / T(1000);
// as long as it is bigger than the used value above
T const limit = T(1) / threshold<T>();
return value > limit;
}
};
Expand Down
4 changes: 4 additions & 0 deletions test/algorithms/buffer/buffer_multi_polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,11 @@ void test_all()
test_one<multi_polygon_type, polygon_type>("nores_6061", nores_6061, join_round32, end_flat, 39.7371, 1.0);
test_one<multi_polygon_type, polygon_type>("nores_37f6", nores_37f6, join_round32, end_flat, 26.5339, 1.0);

#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
// Fails since get_cluster works with an epsilon of 1 (instead of 1000 before).
// With 3 it still succeeds but that causes regression in issue #issue_1081b
test_one<multi_polygon_type, polygon_type>("nores_1ea1", nores_1ea1, join_round32, end_flat, 28.9755, 1.0);
#endif
test_one<multi_polygon_type, polygon_type>("nores_804e", nores_804e, join_round32, end_flat, 26.4503, 1.0);
test_one<multi_polygon_type, polygon_type>("nores_51c6", nores_51c6, join_round32, end_flat, 20.2419, 1.0);
test_one<multi_polygon_type, polygon_type>("nores_e5f3", nores_e5f3, join_round32, end_flat, 14.5503, 1.0);
Expand Down
23 changes: 18 additions & 5 deletions test/algorithms/overlay/get_clusters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void do_test(std::string const& case_id,
}

template <typename Point>
void test_get_clusters(typename bg::coordinate_type<Point>::type eps)
void test_get_clusters()
{
do_test<Point>("no", {{1.0, 1.0}, {1.0, 2.0}}, 0);
do_test<Point>("simplex", {{1.0, 1.0}, {1.0, 1.0}}, 1);
Expand All @@ -80,8 +80,11 @@ void test_get_clusters(typename bg::coordinate_type<Point>::type eps)
6);
do_test<Point>("buffer3", {{6.41421356237, 5},{6.41421356236, 5},{6.70710678119, 5.29289321881},{6.41421356237, 5},{6, 5},{6.41421356238, 5},{7, 5},{8, 10},{8.41421356237, 10},{8, 9.58578643763},{8.41421356237, 10},{7.41421356237, 9},{7.41421356237, 9},{7, 5.58578643763},{7, 5.58578643763},{6, 5},{6, 5},{6, 5},{6, 5},{6, 5},{6, 6},{4, 6},{4, 6},{3.41421356237, 3},{3, 5},{6, 5},{5, 3},{4, 6},{4, 6},{4, 7},{4, 8},{10.9142135624, 5.5},{8, 5},{10.4142135624, 5},{8, 5},{8, 3.58578643763},{8, 5},{9.41421356237, 7},{9.41421356237, 7},{8.91421356237, 7.5},{10, 7},{8, 9},{7.41421356237, 9},{11, 7}},
8);
}

// Border cases
template <typename Point>
void test_get_clusters_border_cases(typename bg::coordinate_type<Point>::type eps)
{
do_test<Point>("borderx_no", {{1, 1}, {1, 2}, {1 + eps * 10, 1}}, 0);
do_test<Point>("borderx_yes", {{1, 1}, {1, 2}, {1 + eps, 1}}, 1);
do_test<Point>("bordery_no", {{1, 1}, {2, 1}, {1 + eps * 10, 1}}, 0);
Expand All @@ -93,8 +96,18 @@ int test_main(int, char* [])
using fp = bg::model::point<float, 2, bg::cs::cartesian>;
using dp = bg::model::point<double, 2, bg::cs::cartesian>;
using ep = bg::model::point<long double, 2, bg::cs::cartesian>;
test_get_clusters<fp>(1.0e-4);
test_get_clusters<dp>(1.0e-13);
test_get_clusters<ep>(1.0e-16);

test_get_clusters<fp>();
test_get_clusters<dp>();
test_get_clusters<ep>();

// This constant relates to the threshold in get_clusters,
// which is now return T(1) (earlier it was 1000)
double const multiplier = 1.0 / 1000.0;

test_get_clusters_border_cases<fp>(1.0e-4 * multiplier);
test_get_clusters_border_cases<dp>(1.0e-13 * multiplier);
test_get_clusters_border_cases<ep>(1.0e-16 * multiplier);

return 0;
}
18 changes: 18 additions & 0 deletions test/algorithms/overlay/overlay_cases.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,6 +1083,24 @@ static std::string issue_1076[2] =
"POLYGON((927.152135631899114 0, 981.792858339935151 98, 995 98, 927.152135631899114 0))"
};

static std::string issue_1081a[2] =
{
"POLYGON((40 100,50 200,75 160,60 160,75 140,40 100),(46.317137830014417 152.14683289288962,59.9312673826029823 167.24190656486104,59.9312673826029823 173.678978034969646,60 175,46.317137830014417 152.14683289288962))",
"POLYGON((65 170,67 140,65 163,56.7651907424660749 163.715020193369355,59.9312673826029823 167.241906564861154,65 170))"
};

static std::string issue_1081b[2] =
{
"POLYGON((21907 0,21917 100,21942 60,21927 60,21942 40,21907 0),(21913.317137830014 52.1468328928896199,21926.9312673826025 67.2419065648610399,21926.9312673826025 73.6789780349696457,21927 75,21913.317137830014 52.1468328928896199))",
"POLYGON((21932 70,21934 40,21932 63,21923.7651907424661 63.7150201933693552,21926.9312673826025 67.2419065648611536,21932 70))"
};

static std::string issue_1081c[2] =
{
"POLYGON((411.083582272653246 134.162757591540753,421.316381618511855 93.3919511307571781,414.749514308625294 94.5205547695399702,414.40388971336813 96.7777620478938587,306.396203695496922 49.799635572622492,411.083582272653246 134.162757591540753),(409.910769975024664 99.8814220555319139,412.848579034710724 101.010025694314677,408.182646998738733 118.926608464425712,409.910769975024664 99.8814220555319139))",
"POLYGON((423.217316892426425 67.5751428875900331,414.40388971336813 96.7777620478938587,410.429206867910466 100.02249750988706,412.848579034710781 101.010025694314706,412.502954439453561 102.98508206238165,416.996074177797027 109.05132662251431,427.364812035512671 72.6538592632950468,423.217316892426425 67.5751428875900331))"
};

static std::string ggl_list_20120229_volker[3] =
{
"POLYGON((1716 1554,2076 2250,2436 2352,2796 1248,3156 2484,3516 2688,3516 2688,3156 2484,2796 1248,2436 2352,2076 2250, 1716 1554))",
Expand Down
5 changes: 3 additions & 2 deletions test/algorithms/set_operations/difference/difference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ void test_all()
1, 5, 8.0);

{
// Sym difference works, but expectations are different for rescaling
ut_settings settings;
settings.validity_false_negative_sym = true;
settings.sym_difference = false;
test_one<polygon, polygon, polygon>("star_comb_15",
star_comb_15[0], star_comb_15[1],
30, -1, 227.658275102812,
Expand Down Expand Up @@ -597,7 +598,7 @@ void test_all()
{
ut_settings settings;
settings.validity_false_negative_sym = true;
TEST_DIFFERENCE_WITH(mysql_23023665_13, 3, 99.74526, 3, 37.74526, 6, settings);
TEST_DIFFERENCE_WITH(mysql_23023665_13, 3, 99.74526, 3, 37.74526, count_set(5, 6), settings);
}
}

Expand Down
9 changes: 9 additions & 0 deletions test/algorithms/set_operations/union/union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,15 @@ void test_areal()
TEST_UNION(issue_1076, 1, 0, -1, 1225.0);
TEST_UNION_REV(issue_1076, 1, 0, -1, 1225.0);

TEST_UNION(issue_1081a, 1, 2, -1, 1600.56);
TEST_UNION_REV(issue_1081a, 1, 2, -1, 1600.56);

TEST_UNION(issue_1081b, 1, 2, -1, 1600.56);
TEST_UNION_REV(issue_1081b, 1, 2, -1, 1600.56);

TEST_UNION(issue_1081c, 1, 1, -1, 2338.08);
TEST_UNION_REV(issue_1081c, 1, 1, -1, 2338.08);

{
// Rescaling produces an invalid result
ut_settings settings;
Expand Down