///|/ Copyright (c) Prusa Research 2019 - 2023 Tomáš Mészáros @tamasmeszaros ///|/ ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher ///|/ #include "MinAreaBoundingBox.hpp" #include #include #if defined(_MSC_VER) && defined(__clang__) #define BOOST_NO_CXX17_HDR_STRING_VIEW #endif #include #include #if !defined(HAS_INTRINSIC_128_TYPE) || defined(__APPLE__) #include #endif #include // IWYU pragma: keep #include #include #include #include #include "libnest2d/common.hpp" #include "libnest2d/geometry_traits.hpp" #include "libslic3r/Polygon.hpp" #include "libslic3r/libslic3r.h" namespace Slic3r { // Used as compute type. using Unit = int64_t; #if !defined(HAS_INTRINSIC_128_TYPE) || defined(__APPLE__) using Rational = boost::rational; #else using Rational = boost::rational<__int128>; #endif template libnest2d::RotatedBox minAreaBoundigBox_( const P &p, MinAreaBoundigBox::PolygonLevel lvl) { P chull = lvl == MinAreaBoundigBox::pcConvex ? p : libnest2d::sl::convexHull(p); libnest2d::removeCollinearPoints(chull); return libnest2d::minAreaBoundingBox(chull); } MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc) { libnest2d::RotatedBox box = minAreaBoundigBox_(p, pc); m_right = libnest2d::cast(box.right_extent()); m_bottom = libnest2d::cast(box.bottom_extent()); m_axis = box.axis(); } MinAreaBoundigBox::MinAreaBoundigBox(const ExPolygon &p, PolygonLevel pc) { libnest2d::RotatedBox box = minAreaBoundigBox_(p, pc); m_right = libnest2d::cast(box.right_extent()); m_bottom = libnest2d::cast(box.bottom_extent()); m_axis = box.axis(); } MinAreaBoundigBox::MinAreaBoundigBox(const Points &pts, PolygonLevel pc) { libnest2d::RotatedBox box = minAreaBoundigBox_(pts, pc); m_right = libnest2d::cast(box.right_extent()); m_bottom = libnest2d::cast(box.bottom_extent()); m_axis = box.axis(); } double MinAreaBoundigBox::angle_to_X() const { double ret = std::atan2(m_axis.y(), m_axis.x()); auto s = std::signbit(ret); if (s) ret += 2 * PI; return -ret; } long double MinAreaBoundigBox::width() const { return std::abs(m_bottom) / std::sqrt(libnest2d::pl::magnsq(m_axis)); } long double MinAreaBoundigBox::height() const { return std::abs(m_right) / std::sqrt(libnest2d::pl::magnsq(m_axis)); } long double MinAreaBoundigBox::area() const { long double asq = libnest2d::pl::magnsq(m_axis); return m_bottom * m_right / asq; } void remove_collinear_points(Polygon &p) { p = libnest2d::removeCollinearPoints(p, Unit(0)); } void remove_collinear_points(ExPolygon &p) { p = libnest2d::removeCollinearPoints(p, Unit(0)); } double fit_into_box_rotation(const Polygon &shape, const BoundingBox &bb) { using namespace libnest2d; _Box box{{bb.min.x(), bb.min.y()}, {bb.max.x(), bb.max.y()}}; return fitIntoBoxRotation, Rational>(shape, box, EPSILON); } } // namespace Slic3r