| 33 | // containing the hull and with one side collinear to the facet. |
| 34 | template <typename Fn> |
| 35 | void ForEachRect(ConvexHull const & hull, Fn && fn) |
| 36 | { |
| 37 | ASSERT_GREATER(hull.Size(), 2, ()); |
| 38 | |
| 39 | size_t j = 0, k = 0, l = 0; |
| 40 | for (size_t i = 0; i < hull.Size(); ++i) |
| 41 | { |
| 42 | auto const ab = hull.SegmentAt(i).Dir(); |
| 43 | |
| 44 | j = std::max(j, i + 1); |
| 45 | while (DotProduct(ab, hull.SegmentAt(j).Dir()) > CalipersBox::kEps) |
| 46 | ++j; |
| 47 | |
| 48 | k = std::max(k, j); |
| 49 | while (CrossProduct(ab, hull.SegmentAt(k).Dir()) > CalipersBox::kEps) |
| 50 | ++k; |
| 51 | |
| 52 | l = std::max(l, k); |
| 53 | while (DotProduct(ab, hull.SegmentAt(l).Dir()) < -CalipersBox::kEps) |
| 54 | ++l; |
| 55 | |
| 56 | auto const oab = Ort(ab); |
| 57 | std::array<Line2D, 4> const lines = {Line2D(hull.PointAt(i), ab), Line2D(hull.PointAt(j), oab), |
| 58 | Line2D(hull.PointAt(k), ab), Line2D(hull.PointAt(l), oab)}; |
| 59 | std::vector<PointD> corners; |
| 60 | for (size_t i = 0; i < lines.size(); ++i) |
| 61 | { |
| 62 | auto const j = (i + 1) % lines.size(); |
| 63 | auto result = Intersect(lines[i], lines[j], CalipersBox::kEps); |
| 64 | if (result.m_type == IntersectionResult::Type::One) |
| 65 | corners.push_back(result.m_point); |
| 66 | } |
| 67 | |
| 68 | if (corners.size() != 4) |
| 69 | continue; |
| 70 | |
| 71 | auto const it = std::min_element(corners.begin(), corners.end()); |
| 72 | std::rotate(corners.begin(), it, corners.end()); |
| 73 | |
| 74 | fn(std::move(corners)); |
| 75 | } |
| 76 | } |
| 77 | } // namespace |
| 78 | |
| 79 | CalipersBox::CalipersBox(std::vector<PointD> const & points) : m_points({}) |
no test coverage detected