mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 07:34:03 -06:00
Adding rotating calipers algorithm for minimum are bounding box rotation.
Cleanup, fix build on windows and add test for rotcalipers. Try to fix compilation on windows With updates from libnest2d Another build fix. Clean up and add comments. adding rotcalipers test and some cleanup Trying to fix on OSX Fix rotcalipers array indexing Get rid of boost convex hull. Adding helper function 'remove_collinear_points' Importing new libnest2d upgrades. Disable using __int128 in NFP on OSX
This commit is contained in:
parent
6136fe7d92
commit
d4fe7b5a96
25 changed files with 1272 additions and 856 deletions
|
@ -163,6 +163,8 @@ add_library(libslic3r STATIC
|
|||
MTUtils.hpp
|
||||
Zipper.hpp
|
||||
Zipper.cpp
|
||||
MinAreaBoundingBox.hpp
|
||||
MinAreaBoundingBox.cpp
|
||||
miniz_extension.hpp
|
||||
miniz_extension.cpp
|
||||
SLA/SLABoilerPlate.hpp
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SLIC3R_INT128_HPP
|
||||
#define SLIC3R_INT128_HPP
|
||||
// #define SLIC3R_DEBUG
|
||||
|
||||
// Make assert active if SLIC3R_DEBUG
|
||||
|
@ -48,6 +50,8 @@
|
|||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
|
||||
#if ! defined(_MSC_VER) && defined(__SIZEOF_INT128__)
|
||||
#define HAS_INTRINSIC_128_TYPE
|
||||
|
@ -293,3 +297,5 @@ public:
|
|||
return sign_determinant_2x2(p1, q1, p2, q2) * invert;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SLIC3R_INT128_HPP
|
||||
|
|
142
src/libslic3r/MinAreaBoundingBox.cpp
Normal file
142
src/libslic3r/MinAreaBoundingBox.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
#include "MinAreaBoundingBox.hpp"
|
||||
|
||||
#include <libslic3r/ExPolygon.hpp>
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
#include <libslic3r/Int128.hpp>
|
||||
|
||||
#if !defined(HAS_INTRINSIC_128_TYPE) || defined(__APPLE__)
|
||||
#include <boost/multiprecision/integer.hpp>
|
||||
#endif
|
||||
|
||||
#include <libnest2d/geometry_traits.hpp>
|
||||
#include <libnest2d/utils/rotcalipers.hpp>
|
||||
|
||||
namespace libnest2d {
|
||||
|
||||
template<> struct PointType<Slic3r::Points> { using Type = Slic3r::Point; };
|
||||
template<> struct CoordType<Slic3r::Point> { using Type = coord_t; };
|
||||
template<> struct ShapeTag<Slic3r::ExPolygon> { using Type = PolygonTag; };
|
||||
template<> struct ShapeTag<Slic3r::Polygon> { using Type = PolygonTag; };
|
||||
template<> struct ShapeTag<Slic3r::Points> { using Type = PathTag; };
|
||||
template<> struct ShapeTag<Slic3r::Point> { using Type = PointTag; };
|
||||
template<> struct ContourType<Slic3r::ExPolygon> { using Type = Slic3r::Points; };
|
||||
template<> struct ContourType<Slic3r::Polygon> { using Type = Slic3r::Points; };
|
||||
|
||||
namespace pointlike {
|
||||
|
||||
template<> inline coord_t x(const Slic3r::Point& p) { return p.x(); }
|
||||
template<> inline coord_t y(const Slic3r::Point& p) { return p.y(); }
|
||||
template<> inline coord_t& x(Slic3r::Point& p) { return p.x(); }
|
||||
template<> inline coord_t& y(Slic3r::Point& p) { return p.y(); }
|
||||
|
||||
} // pointlike
|
||||
|
||||
namespace shapelike {
|
||||
template<> inline Slic3r::Points& contour(Slic3r::ExPolygon& sh) { return sh.contour.points; }
|
||||
template<> inline const Slic3r::Points& contour(const Slic3r::ExPolygon& sh) { return sh.contour.points; }
|
||||
template<> inline Slic3r::Points& contour(Slic3r::Polygon& sh) { return sh.points; }
|
||||
template<> inline const Slic3r::Points& contour(const Slic3r::Polygon& sh) { return sh.points; }
|
||||
|
||||
template<> Slic3r::Points::iterator begin(Slic3r::Points& pts, const PathTag&) { return pts.begin();}
|
||||
template<> Slic3r::Points::const_iterator cbegin(const Slic3r::Points& pts, const PathTag&) { return pts.begin(); }
|
||||
template<> Slic3r::Points::iterator end(Slic3r::Points& pts, const PathTag&) { return pts.end();}
|
||||
template<> Slic3r::Points::const_iterator cend(const Slic3r::Points& pts, const PathTag&) { return pts.cend(); }
|
||||
|
||||
template<> inline Slic3r::ExPolygon create<Slic3r::ExPolygon>(Slic3r::Points&& contour)
|
||||
{
|
||||
Slic3r::ExPolygon expoly; expoly.contour.points.swap(contour);
|
||||
return expoly;
|
||||
}
|
||||
|
||||
template<> inline Slic3r::Polygon create<Slic3r::Polygon>(Slic3r::Points&& contour)
|
||||
{
|
||||
Slic3r::Polygon poly; poly.points.swap(contour);
|
||||
return poly;
|
||||
}
|
||||
|
||||
} // shapelike
|
||||
} // libnest2d
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Used as compute type.
|
||||
using Unit = int64_t;
|
||||
|
||||
#if !defined(HAS_INTRINSIC_128_TYPE) || defined(__APPLE__)
|
||||
using Rational = boost::rational<boost::multiprecision::int128_t>;
|
||||
#else
|
||||
using Rational = boost::rational<__int128>;
|
||||
#endif
|
||||
|
||||
MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc)
|
||||
{
|
||||
const Polygon& chull = pc == pcConvex ? p : libnest2d::sl::convexHull(p);
|
||||
|
||||
libnest2d::RotatedBox<Point, Unit> box =
|
||||
libnest2d::minAreaBoundingBox<Polygon, Unit, Rational>(chull);
|
||||
|
||||
m_right = box.right_extent();
|
||||
m_bottom = box.bottom_extent();
|
||||
m_axis = box.axis();
|
||||
}
|
||||
|
||||
MinAreaBoundigBox::MinAreaBoundigBox(const ExPolygon &p, PolygonLevel pc)
|
||||
{
|
||||
const ExPolygon& chull = pc == pcConvex ? p : libnest2d::sl::convexHull(p);
|
||||
|
||||
libnest2d::RotatedBox<Point, Unit> box =
|
||||
libnest2d::minAreaBoundingBox<ExPolygon, Unit, Rational>(chull);
|
||||
|
||||
m_right = box.right_extent();
|
||||
m_bottom = box.bottom_extent();
|
||||
m_axis = box.axis();
|
||||
}
|
||||
|
||||
MinAreaBoundigBox::MinAreaBoundigBox(const Points &pts, PolygonLevel pc)
|
||||
{
|
||||
const Points& chull = pc == pcConvex ? pts : libnest2d::sl::convexHull(pts);
|
||||
|
||||
libnest2d::RotatedBox<Point, Unit> box =
|
||||
libnest2d::minAreaBoundingBox<Points, Unit, Rational>(chull);
|
||||
|
||||
m_right = box.right_extent();
|
||||
m_bottom = 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<Point, long double>(m_axis));
|
||||
}
|
||||
|
||||
long double MinAreaBoundigBox::height() const
|
||||
{
|
||||
return std::abs(m_right) / std::sqrt(libnest2d::pl::magnsq<Point, long double>(m_axis));
|
||||
}
|
||||
|
||||
long double MinAreaBoundigBox::area() const
|
||||
{
|
||||
long double asq = libnest2d::pl::magnsq<Point, long double>(m_axis);
|
||||
return m_bottom * m_right / asq;
|
||||
}
|
||||
|
||||
void remove_collinear_points(Polygon &p)
|
||||
{
|
||||
p = libnest2d::removeCollinearPoints<Polygon>(p, Unit(0));
|
||||
}
|
||||
|
||||
void remove_collinear_points(ExPolygon &p)
|
||||
{
|
||||
p = libnest2d::removeCollinearPoints<ExPolygon>(p, Unit(0));
|
||||
}
|
||||
|
||||
}
|
59
src/libslic3r/MinAreaBoundingBox.hpp
Normal file
59
src/libslic3r/MinAreaBoundingBox.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#ifndef MINAREABOUNDINGBOX_HPP
|
||||
#define MINAREABOUNDINGBOX_HPP
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Polygon;
|
||||
class ExPolygon;
|
||||
|
||||
void remove_collinear_points(Polygon& p);
|
||||
void remove_collinear_points(ExPolygon& p);
|
||||
|
||||
/// A class that holds a rotated bounding box. If instantiated with a polygon
|
||||
/// type it will hold the minimum area bounding box for the given polygon.
|
||||
/// If the input polygon is convex, the complexity is linear to the number of
|
||||
/// points. Otherwise a convex hull of O(n*log(n)) has to be performed.
|
||||
class MinAreaBoundigBox {
|
||||
Point m_axis;
|
||||
long double m_bottom = 0.0l, m_right = 0.0l;
|
||||
public:
|
||||
|
||||
// Polygons can be convex or simple (convex or concave with possible holes)
|
||||
enum PolygonLevel {
|
||||
pcConvex, pcSimple
|
||||
};
|
||||
|
||||
// Constructors with various types of geometry data used in Slic3r.
|
||||
// If the convexity is known apriory, pcConvex can be used to skip
|
||||
// convex hull calculation. It is very important that the input polygons
|
||||
// do NOT have any collinear points (except for the first and the last
|
||||
// vertex being the same -- meaning a closed polygon for boost)
|
||||
// To make sure this constraint is satisfied, you can call
|
||||
// remove_collinear_points on the input polygon before handing over here)
|
||||
explicit MinAreaBoundigBox(const Polygon&, PolygonLevel = pcSimple);
|
||||
explicit MinAreaBoundigBox(const ExPolygon&, PolygonLevel = pcSimple);
|
||||
explicit MinAreaBoundigBox(const Points&, PolygonLevel = pcSimple);
|
||||
|
||||
// Returns the angle in radians needed for the box to be aligned with the
|
||||
// X axis. Rotate the polygon by this angle and it will be aligned.
|
||||
double angle_to_X() const;
|
||||
|
||||
// The box width
|
||||
long double width() const;
|
||||
|
||||
// The box height
|
||||
long double height() const;
|
||||
|
||||
// The box area
|
||||
long double area() const;
|
||||
|
||||
// The axis of the rotated box. If the angle_to_X is not sufficiently
|
||||
// precise, use this unnormalized direction vector.
|
||||
const Point& axis() const { return m_axis; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MINAREABOUNDINGBOX_HPP
|
|
@ -9,6 +9,31 @@
|
|||
#include <ClipperUtils.hpp>
|
||||
|
||||
#include <boost/geometry/index/rtree.hpp>
|
||||
#include <boost/multiprecision/integer.hpp>
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
namespace libnest2d {
|
||||
#if !defined(_MSC_VER) && defined(__SIZEOF_INT128__) && !defined(__APPLE__)
|
||||
using LargeInt = __int128;
|
||||
#else
|
||||
using LargeInt = boost::multiprecision::int128_t;
|
||||
template<> struct _NumTag<LargeInt> { using Type = ScalarTag; };
|
||||
#endif
|
||||
template<class T> struct _NumTag<boost::rational<T>> { using Type = RationalTag; };
|
||||
|
||||
namespace nfp {
|
||||
|
||||
template<class S>
|
||||
struct NfpImpl<S, NfpLevel::CONVEX_ONLY>
|
||||
{
|
||||
NfpResult<S> operator()(const S &sh, const S &other)
|
||||
{
|
||||
return nfpConvexOnly<S, boost::rational<LargeInt>>(sh, other);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -130,7 +155,7 @@ Box boundingBox(const Box& pilebb, const Box& ibb ) {
|
|||
// at the same time, it has to provide reasonable results.
|
||||
std::tuple<double /*score*/, Box /*farthest point from bin center*/>
|
||||
objfunc(const PointImpl& bincenter,
|
||||
const shapelike::Shapes<PolygonImpl>& merged_pile,
|
||||
const TMultiShape<PolygonImpl>& merged_pile,
|
||||
const Box& pilebb,
|
||||
const ItemGroup& items,
|
||||
const Item &item,
|
||||
|
@ -301,7 +326,7 @@ protected:
|
|||
using Packer = Nester<Placer, Selector>;
|
||||
using PConfig = typename Packer::PlacementConfig;
|
||||
using Distance = TCoord<PointImpl>;
|
||||
using Pile = sl::Shapes<PolygonImpl>;
|
||||
using Pile = TMultiShape<PolygonImpl>;
|
||||
|
||||
Packer m_pck;
|
||||
PConfig m_pconf; // Placement configuration
|
||||
|
@ -589,7 +614,7 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model, const WipeTowerInfo&
|
|||
|
||||
// Invalid geometries would throw exceptions when arranging
|
||||
if(item.vertexCount() > 3) {
|
||||
item.rotation(float(Geometry::rotation_diff_z(rotation0, objinst->get_rotation()))),
|
||||
item.rotation(Geometry::rotation_diff_z(rotation0, objinst->get_rotation()));
|
||||
item.translation({
|
||||
ClipperLib::cInt(objinst->get_offset(X)/SCALING_FACTOR),
|
||||
ClipperLib::cInt(objinst->get_offset(Y)/SCALING_FACTOR)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue