From 4cc1b2740d0deb3391affdafc884fb975228b7e0 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 4 Oct 2021 14:16:13 +0200 Subject: [PATCH] Don't report intersection if two polygons are only touching. --- src/libslic3r/Geometry.cpp | 35 +++++++++++++------------------ src/libslic3r/Geometry.hpp | 4 +++- tests/libslic3r/test_geometry.cpp | 22 ++++++++++++------- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 10c617c60..d1b78a02c 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1554,14 +1554,16 @@ namespace rotcalip { using int256_t = boost::multiprecision::int256_t; using int128_t = boost::multiprecision::int128_t; -inline int128_t magnsq(const Point &p) +template +inline Scalar magnsq(const Point &p) { - return int128_t(p.x()) * p.x() + int64_t(p.y()) * p.y(); + return Scalar(p.x()) * p.x() + Scalar(p.y()) * p.y(); } -inline int128_t dot(const Point &a, const Point &b) +template +inline Scalar dot(const Point &a, const Point &b) { - return int128_t(a.x()) * b.x() + int64_t(a.y()) * b.y(); + return Scalar(a.x()) * b.x() + Scalar(a.y()) * b.y(); } template @@ -1667,7 +1669,6 @@ bool intersects(const Polygon &A, const Polygon &B) // Establish starting antipodals as extremes in XY plane. Use the // easily obtainable bounding boxes to check if A and B is disjoint // and return false if the are. - struct BB { size_t xmin = 0, xmax = 0, ymin = 0, ymax = 0; @@ -1724,24 +1725,18 @@ bool intersects(const Polygon &A, const Polygon &B) bool is_left_a = dotperp( dir, ref_a - A[ia]) > 0; bool is_left_b = dotperp(-dir, ref_b - B[ib]) > 0; - // If both reference points are on the left (or right) of the - // support line and the opposite support line is to the righ (or - // left), the divisor line is found. We only test the reference - // point, as by definition, if that is on one side, all the other - // points must be on the same side of a support line. + // If both reference points are on the left (or right) of their + // respective support lines and the opposite support line is to + // the right (or left), the divisor line is found. We only test + // the reference point, as by definition, if that is on one side, + // all the other points must be on the same side of a support + // line. If the support lines are collinear, the polygons must be + // on the same side of their respective support lines. auto d = dotperp(dir, B[ib] - A[ia]); - if (d == 0 && ((is_left_a && is_left_b) || (!is_left_a && !is_left_b))) { + if (d == 0) { // The caliper lines are collinear, not just parallel - - // Check if the lines are overlapping and if they do ignore the divisor - Point a = A[ia], b = A[(ia + 1) % A.size()]; - if (b < a) std::swap(a, b); - Point c = B[ib], d = B[(ib + 1) % B.size()]; - if (d < c) std::swap(c, d); - - found_divisor = b < c; - + found_divisor = (is_left_a && is_left_b) || (!is_left_a && !is_left_b); } else if (d > 0) { // B is to the left of (A, A+1) found_divisor = !is_left_a && !is_left_b; } else { // B is to the right of (A, A+1) diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index bb583c33c..505ff3d96 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -532,7 +532,9 @@ inline bool is_rotation_ninety_degrees(const Vec3d &rotation) return is_rotation_ninety_degrees(rotation.x()) && is_rotation_ninety_degrees(rotation.y()) && is_rotation_ninety_degrees(rotation.z()); } -bool intersects(const Polygon &convex_poly1, const Polygon &convex_poly2); +// Returns true if the intersection of the two convex polygons A and B +// is not an empty set. +bool intersects(const Polygon &A, const Polygon &B); } } // namespace Slicer::Geometry diff --git a/tests/libslic3r/test_geometry.cpp b/tests/libslic3r/test_geometry.cpp index 308e29fca..b183de1b4 100644 --- a/tests/libslic3r/test_geometry.cpp +++ b/tests/libslic3r/test_geometry.cpp @@ -470,7 +470,7 @@ TEST_CASE("Convex polygon intersection on two disjoint squares", "[Geometry][Rot bool is_inters = Geometry::intersects(A, B); - REQUIRE(is_inters != true); + REQUIRE(is_inters == false); } TEST_CASE("Convex polygon intersection on two intersecting squares", "[Geometry][Rotcalip]") { @@ -494,7 +494,7 @@ TEST_CASE("Convex polygon intersection on two squares touching one edge", "[Geom bool is_inters = Geometry::intersects(A, B); - REQUIRE(is_inters == true); + REQUIRE(is_inters == false); } TEST_CASE("Convex polygon intersection on two squares touching one vertex", "[Geometry][Rotcalip]") { @@ -502,11 +502,16 @@ TEST_CASE("Convex polygon intersection on two squares touching one vertex", "[Ge A.scale(1. / SCALING_FACTOR); Polygon B = A; - B.translate(10 / SCALING_FACTOR, 10); + B.translate(10 / SCALING_FACTOR, 10 / SCALING_FACTOR); + + SVG svg{std::string("one_vertex_touch") + ".svg"}; + svg.draw(A, "blue"); + svg.draw(B, "green"); + svg.Close(); bool is_inters = Geometry::intersects(A, B); - REQUIRE(is_inters == true); + REQUIRE(is_inters == false); } TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][Rotcalip]") { @@ -520,7 +525,7 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][ REQUIRE(is_inters == true); } -// Only for benchmarking +//// Only for benchmarking //static Polygon gen_convex_poly(std::mt19937_64 &rg, size_t point_cnt) //{ // std::uniform_int_distribution dist(0, 100); @@ -540,7 +545,9 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][ // constexpr size_t TEST_CNT = 1000; // constexpr size_t POINT_CNT = 1000; -// std::mt19937_64 rg{std::random_device{}()}; +// auto seed = std::random_device{}(); +//// unsigned long seed = 2525634386; +// std::mt19937_64 rg{seed}; // Benchmark bench; // auto tests = reserve_vector>(TEST_CNT); @@ -567,11 +574,12 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][ // REQUIRE(results.size() == expects.size()); +// auto seedstr = std::to_string(seed); // for (size_t i = 0; i < results.size(); ++i) { // // std::cout << expects[i] << " "; // if (results[i] != expects[i]) { -// SVG svg{std::string("fail") + std::to_string(i) + ".svg"}; +// SVG svg{std::string("fail_seed") + seedstr + "_" + std::to_string(i) + ".svg"}; // svg.draw(tests[i].first, "blue"); // svg.draw(tests[i].second, "green"); // svg.Close();