Moved some math macros (sqr, lerp, clamp) to libslic3r.h
Added UNUSED macro to libslic3r.h, used it to reduce some compile warnings. Split the Int128 class from Clipper library to a separate file, extended Int128 with intrinsic types wherever possible for performance, added new geometric predicates. Added a draft of new FillRectilinear3, which should reduce overfill near the perimeters in the future.
This commit is contained in:
parent
3b51f64411
commit
a6ea01a23f
19 changed files with 2106 additions and 289 deletions
|
@ -49,6 +49,7 @@
|
|||
#include <functional>
|
||||
#include <assert.h>
|
||||
#include <Shiny/Shiny.h>
|
||||
#include <libslic3r/Int128.hpp>
|
||||
|
||||
namespace ClipperLib {
|
||||
|
||||
|
@ -128,109 +129,6 @@ bool PolyNode::IsHole() const
|
|||
}
|
||||
return result;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Int128 class (enables safe math on signed 64bit integers)
|
||||
// eg Int128 val1((int64_t)9223372036854775807); //ie 2^63 -1
|
||||
// Int128 val2((int64_t)9223372036854775807);
|
||||
// Int128 val3 = val1 * val2;
|
||||
// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37)
|
||||
//------------------------------------------------------------------------------
|
||||
// Used by the SlopesEqual() functions.
|
||||
class Int128
|
||||
{
|
||||
public:
|
||||
uint64_t lo;
|
||||
int64_t hi;
|
||||
|
||||
Int128(int64_t _lo = 0) : lo((uint64_t)_lo), hi((_lo < 0) ? -1 : 0) {}
|
||||
Int128(const Int128 &val) : lo(val.lo), hi(val.hi) {}
|
||||
Int128(const int64_t& _hi, const uint64_t& _lo) : lo(_lo), hi(_hi) {}
|
||||
|
||||
Int128& operator = (const int64_t &val)
|
||||
{
|
||||
lo = (uint64_t)val;
|
||||
hi = (val < 0) ? -1 : 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator == (const Int128 &val) const { return hi == val.hi && lo == val.lo; }
|
||||
bool operator != (const Int128 &val) const { return ! (*this == val); }
|
||||
bool operator > (const Int128 &val) const { return (hi == val.hi) ? lo > val.lo : hi > val.hi; }
|
||||
bool operator < (const Int128 &val) const { return (hi == val.hi) ? lo < val.lo : hi < val.hi; }
|
||||
bool operator >= (const Int128 &val) const { return ! (*this < val); }
|
||||
bool operator <= (const Int128 &val) const { return ! (*this > val); }
|
||||
|
||||
Int128& operator += (const Int128 &rhs)
|
||||
{
|
||||
hi += rhs.hi;
|
||||
lo += rhs.lo;
|
||||
if (lo < rhs.lo) hi++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 operator + (const Int128 &rhs) const
|
||||
{
|
||||
Int128 result(*this);
|
||||
result+= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
Int128& operator -= (const Int128 &rhs)
|
||||
{
|
||||
*this += -rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 operator - (const Int128 &rhs) const
|
||||
{
|
||||
Int128 result(*this);
|
||||
result -= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
Int128 operator-() const { return (lo == 0) ? Int128(-hi, 0) : Int128(~hi, ~lo + 1); }
|
||||
|
||||
operator double() const
|
||||
{
|
||||
const double shift64 = 18446744073709551616.0; //2^64
|
||||
return (hi < 0) ?
|
||||
((lo == 0) ?
|
||||
(double)hi * shift64 :
|
||||
-(double)(~lo + ~hi * shift64)) :
|
||||
(double)(lo + hi * shift64);
|
||||
}
|
||||
|
||||
static inline Int128 Multiply(int64_t lhs, int64_t rhs)
|
||||
{
|
||||
bool negate = (lhs < 0) != (rhs < 0);
|
||||
|
||||
if (lhs < 0) lhs = -lhs;
|
||||
uint64_t int1Hi = uint64_t(lhs) >> 32;
|
||||
uint64_t int1Lo = uint64_t(lhs & 0xFFFFFFFF);
|
||||
|
||||
if (rhs < 0) rhs = -rhs;
|
||||
uint64_t int2Hi = uint64_t(rhs) >> 32;
|
||||
uint64_t int2Lo = uint64_t(rhs & 0xFFFFFFFF);
|
||||
|
||||
//because the high (sign) bits in both int1Hi & int2Hi have been zeroed,
|
||||
//there's no risk of 64 bit overflow in the following assignment
|
||||
//(ie: $7FFFFFFF*$FFFFFFFF + $7FFFFFFF*$FFFFFFFF < 64bits)
|
||||
uint64_t a = int1Hi * int2Hi;
|
||||
uint64_t b = int1Lo * int2Lo;
|
||||
//Result = A shl 64 + C shl 32 + B ...
|
||||
uint64_t c = int1Hi * int2Lo + int1Lo * int2Hi;
|
||||
|
||||
Int128 tmp;
|
||||
tmp.hi = int64_t(a + (c >> 32));
|
||||
tmp.lo = int64_t(c << 32);
|
||||
tmp.lo += int64_t(b);
|
||||
if (tmp.lo < b) tmp.hi++;
|
||||
if (negate) tmp = -tmp;
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Miscellaneous global functions
|
||||
|
@ -375,32 +273,11 @@ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
|
|||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Approximate calculation of SlopesEqual() for "UseFullInt64Range"
|
||||
// Returns true if the slopes are unequal for sure,
|
||||
// otherwise returns false if the slopes may or may not be equal.
|
||||
inline bool SlopesUnequalFilter(cInt dx1, cInt dy1, cInt dx2, cInt dy2) {
|
||||
// Round dx1, dy1, dx2, dy2 to 31 bits.
|
||||
dx1 = (dx1 + (1 << 30)) >> 32;
|
||||
dy1 = (dy1 + (1 << 30)) >> 32;
|
||||
dx2 = (dx2 + (1 << 30)) >> 32;
|
||||
dy2 = (dy2 + (1 << 30)) >> 32;
|
||||
// Result fits 63 bits, it is an approximate of the determinant divided by 2^64.
|
||||
cInt discr = std::abs(dy1 * dx2 - dx1 * dy2);
|
||||
// Maximum absolute of the remainder of the exact determinant, divided by 2^64.
|
||||
cInt error = ((std::abs(dx1) + std::abs(dy1) + std::abs(dx2) + std::abs(dy2)) >> 1) + 1;
|
||||
return discr > error;
|
||||
}
|
||||
|
||||
inline bool SlopesEqual(const cInt dx1, const cInt dy1, const cInt dx2, const cInt dy2, bool UseFullInt64Range) {
|
||||
return (UseFullInt64Range) ?
|
||||
// |dx1| < 2^63, |dx2| < 2^63 etc,
|
||||
#if 1
|
||||
// Instead of jumping to 128bit multiply on a 32bit or 64bit CPU,
|
||||
// calculate an approximate value of the determinant and its error.
|
||||
// If the determinant is above the error, the slopes are certainly not equal.
|
||||
! SlopesUnequalFilter(dx1, dy1, dx2, dy2) &&
|
||||
#endif
|
||||
Int128::Multiply(dy1, dx2) == Int128::Multiply(dx1, dy2) :
|
||||
Int128::sign_determinant_2x2_filtered(dx1, dy1, dx2, dy2) == 0 :
|
||||
// Int128::sign_determinant_2x2(dx1, dy1, dx2, dy2) == 0 :
|
||||
// |dx1| < 2^31, |dx2| < 2^31 etc,
|
||||
// therefore the following computation could be done with 64bit arithmetics.
|
||||
dy1 * dx2 == dx1 * dy2;
|
||||
|
|
|
@ -95,6 +95,7 @@ public:
|
|||
};
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
std::istringstream iss(str);
|
||||
iss >> this->value;
|
||||
return !iss.fail();
|
||||
|
@ -155,6 +156,7 @@ public:
|
|||
};
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
std::istringstream iss(str);
|
||||
iss >> this->value;
|
||||
return !iss.fail();
|
||||
|
@ -210,6 +212,7 @@ public:
|
|||
}
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
return unescape_string_cstyle(str, this->value);
|
||||
};
|
||||
};
|
||||
|
@ -252,6 +255,7 @@ public:
|
|||
};
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
// don't try to parse the trailing % since it's optional
|
||||
std::istringstream iss(str);
|
||||
iss >> this->value;
|
||||
|
@ -333,6 +337,7 @@ public:
|
|||
};
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
this->percent = str.find_first_of("%") != std::string::npos;
|
||||
std::istringstream iss(str);
|
||||
iss >> this->value;
|
||||
|
@ -355,6 +360,7 @@ public:
|
|||
};
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
std::istringstream iss(str);
|
||||
iss >> this->value.x;
|
||||
iss.ignore(std::numeric_limits<std::streamsize>::max(), ',');
|
||||
|
@ -422,6 +428,7 @@ public:
|
|||
};
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
this->value = (str.compare("1") == 0);
|
||||
return true;
|
||||
};
|
||||
|
@ -481,6 +488,7 @@ public:
|
|||
};
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
t_config_enum_values enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
|
||||
if (enum_keys_map.count(str) == 0) return false;
|
||||
this->value = static_cast<T>(enum_keys_map[str]);
|
||||
|
@ -508,6 +516,7 @@ public:
|
|||
};
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) {
|
||||
UNUSED(append);
|
||||
if (this->keys_map->count(str) == 0) return false;
|
||||
this->value = (*const_cast<t_config_enum_values*>(this->keys_map))[str];
|
||||
return true;
|
||||
|
|
|
@ -13,12 +13,15 @@
|
|||
|
||||
#include <boost/multi_array.hpp>
|
||||
|
||||
#include "libslic3r.h"
|
||||
#include "ExtrusionSimulator.hpp"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Replacement for a template alias.
|
||||
// Shorthand for the point_xy.
|
||||
template<typename T>
|
||||
|
@ -172,24 +175,6 @@ inline T mag(const boost::geometry::model::d2::point_xy<T> &v)
|
|||
return l2(v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T lerp(T start, T end, T alpha)
|
||||
{
|
||||
return start * (T(1.) - alpha) + end * alpha;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T clamp(T low, T high, T x)
|
||||
{
|
||||
return std::max<T>(low, std::min<T>(high, x));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T sqr(T x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T dist2_to_line(
|
||||
const boost::geometry::model::d2::point_xy<T> &p0,
|
||||
|
@ -657,7 +642,7 @@ void gcode_spread_points(
|
|||
A2f &acc,
|
||||
const A2f &mask,
|
||||
const ExtrusionPoints &points,
|
||||
Slic3r::ExtrusionSimulationType simulationType)
|
||||
ExtrusionSimulationType simulationType)
|
||||
{
|
||||
int nc = acc.shape()[1];
|
||||
int nr = acc.shape()[0];
|
||||
|
@ -796,14 +781,14 @@ void gcode_spread_points(
|
|||
// if (true) {
|
||||
// printf("volume_total: %f, volume_full: %f, fill factor: %f\n", volume_total, volume_full, 100.f - 100.f * volume_total / volume_full);
|
||||
// printf("volume_full: %f, volume_excess+deficit: %f, volume_excess: %f, volume_deficit: %f\n", volume_full, volume_excess+volume_deficit, volume_excess, volume_deficit);
|
||||
if (simulationType == Slic3r::ExtrusionSimulationSpreadFull || volume_total <= volume_full) {
|
||||
if (simulationType == ExtrusionSimulationSpreadFull || volume_total <= volume_full) {
|
||||
// The volume under the circle is spreaded fully.
|
||||
float height_avg = volume_total / area_total;
|
||||
for (size_t i = 0; i < n_cells; ++ i) {
|
||||
const Cell &cell = cells[i];
|
||||
acc[cell.idx.y()][cell.idx.x()] = (1.f - cell.fraction_covered) * cell.volume + cell.fraction_covered * cell.area * height_avg;
|
||||
}
|
||||
} else if (simulationType == Slic3r::ExtrusionSimulationSpreadExcess) {
|
||||
} else if (simulationType == ExtrusionSimulationSpreadExcess) {
|
||||
// The volume under the circle does not fit.
|
||||
// 1) Fill the underfilled cells and remove them from the list.
|
||||
float volume_borrowed_total = 0.;
|
||||
|
@ -881,8 +866,6 @@ inline std::vector<V3uc> CreatePowerColorGradient24bit()
|
|||
return out;
|
||||
}
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class ExtrusionSimulatorImpl {
|
||||
public:
|
||||
std::vector<unsigned char> image_data;
|
||||
|
|
|
@ -50,12 +50,6 @@ static std::vector<coordf_t> perpendPoints(const coordf_t offset, const size_t b
|
|||
return points;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline T clamp(T low, T high, T x)
|
||||
{
|
||||
return std::max<T>(low, std::min<T>(high, x));
|
||||
}
|
||||
|
||||
// Trims an array of points to specified rectangular limits. Point
|
||||
// components that are outside these limits are set to the limits.
|
||||
static inline void trim(Pointfs &pts, coordf_t minX, coordf_t minY, coordf_t maxX, coordf_t maxY)
|
||||
|
|
|
@ -95,21 +95,19 @@ protected:
|
|||
|
||||
// The expolygon may be modified by the method to avoid a copy.
|
||||
virtual void _fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon &expolygon,
|
||||
Polylines &polylines_out) {}
|
||||
const FillParams & /* params */,
|
||||
unsigned int /* thickness_layers */,
|
||||
const std::pair<float, Point> & /* direction */,
|
||||
ExPolygon & /* expolygon */,
|
||||
Polylines & /* polylines_out */) {};
|
||||
|
||||
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
|
||||
|
||||
virtual float _layer_angle(size_t idx) const {
|
||||
bool odd = idx & 1;
|
||||
return (idx & 1) ? float(M_PI/2.) : 0;
|
||||
}
|
||||
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }
|
||||
|
||||
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
||||
|
||||
public:
|
||||
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
|
||||
|
||||
// Align a coordinate to a grid. The coordinate may be negative,
|
||||
// the aligned value will never be bigger than the original one.
|
||||
static coord_t _align_to_grid(const coord_t coord, const coord_t spacing) {
|
||||
|
|
|
@ -38,8 +38,8 @@ void FillConcentric::_fill_surface_single(
|
|||
// split paths using a nearest neighbor search
|
||||
size_t iPathFirst = polylines_out.size();
|
||||
Point last_pos(0, 0);
|
||||
for (Polygons::const_iterator it_loop = loops.begin(); it_loop != loops.end(); ++ it_loop) {
|
||||
polylines_out.push_back(it_loop->split_at_index(last_pos.nearest_point_index(*it_loop)));
|
||||
for (const Polygon &loop : loops) {
|
||||
polylines_out.push_back(loop.split_at_index(last_pos.nearest_point_index(loop)));
|
||||
last_pos = polylines_out.back().last_point();
|
||||
}
|
||||
|
||||
|
@ -50,13 +50,15 @@ void FillConcentric::_fill_surface_single(
|
|||
polylines_out[i].clip_end(this->loop_clipping);
|
||||
if (polylines_out[i].is_valid()) {
|
||||
if (j < i)
|
||||
std::swap(polylines_out[j], polylines_out[i]);
|
||||
polylines_out[j] = std::move(polylines_out[i]);
|
||||
++ j;
|
||||
}
|
||||
}
|
||||
if (j < polylines_out.size())
|
||||
polylines_out.erase(polylines_out.begin() + j, polylines_out.end());
|
||||
// TODO: return ExtrusionLoop objects to get better chained paths
|
||||
//TODO: return ExtrusionLoop objects to get better chained paths,
|
||||
// otherwise the outermost loop starts at the closest point to (0, 0).
|
||||
// We want the loops to be split inside the G-code generator to get optimum path planning.
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -33,36 +33,6 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
#ifndef clamp
|
||||
template<typename T>
|
||||
static inline T clamp(T low, T high, T x)
|
||||
{
|
||||
return std::max<T>(low, std::min<T>(high, x));
|
||||
}
|
||||
#endif /* clamp */
|
||||
|
||||
#ifndef sqr
|
||||
template<typename T>
|
||||
static inline T sqr(T x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
#endif /* sqr */
|
||||
|
||||
#ifndef mag2
|
||||
static inline coordf_t mag2(const Point &p)
|
||||
{
|
||||
return sqr(coordf_t(p.x)) + sqr(coordf_t(p.y));
|
||||
}
|
||||
#endif /* mag2 */
|
||||
|
||||
#ifndef mag
|
||||
static inline coordf_t mag(const Point &p)
|
||||
{
|
||||
return std::sqrt(mag2(p));
|
||||
}
|
||||
#endif /* mag */
|
||||
|
||||
// Having a segment of a closed polygon, calculate its Euclidian length.
|
||||
// The segment indices seg1 and seg2 signify an end point of an edge in the forward direction of the loop,
|
||||
// therefore the point p1 lies on poly.points[seg1-1], poly.points[seg1] etc.
|
||||
|
|
1621
xs/src/libslic3r/Fill/FillRectilinear3.cpp
Normal file
1621
xs/src/libslic3r/Fill/FillRectilinear3.cpp
Normal file
File diff suppressed because it is too large
Load diff
83
xs/src/libslic3r/Fill/FillRectilinear3.hpp
Normal file
83
xs/src/libslic3r/Fill/FillRectilinear3.hpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#ifndef slic3r_FillRectilinear2_hpp_
|
||||
#define slic3r_FillRectilinear2_hpp_
|
||||
|
||||
#include "../libslic3r.h"
|
||||
|
||||
#include "FillBase.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Surface;
|
||||
|
||||
class FillRectilinear3 : public Fill
|
||||
{
|
||||
public:
|
||||
virtual Fill* clone() const { return new FillRectilinear3(*this); };
|
||||
virtual ~FillRectilinear3() {}
|
||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||
|
||||
struct FillDirParams
|
||||
{
|
||||
FillDirParams(coordf_t spacing, double angle, coordf_t pattern_shift = 0.f) :
|
||||
spacing(spacing), angle(angle), pattern_shift(pattern_shift) {}
|
||||
coordf_t spacing;
|
||||
double angle;
|
||||
coordf_t pattern_shift;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, std::vector<FillDirParams> &fill_dir_params, Polylines &polylines_out);
|
||||
};
|
||||
|
||||
class FillGrid3 : public FillRectilinear3
|
||||
{
|
||||
public:
|
||||
virtual Fill* clone() const { return new FillGrid3(*this); };
|
||||
virtual ~FillGrid3() {}
|
||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
virtual float _layer_angle(size_t /* idx */) const { return 0.f; }
|
||||
};
|
||||
|
||||
class FillTriangles3 : public FillRectilinear3
|
||||
{
|
||||
public:
|
||||
virtual Fill* clone() const { return new FillTriangles3(*this); };
|
||||
virtual ~FillTriangles3() {}
|
||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
virtual float _layer_angle(size_t /* idx */) const { return 0.f; }
|
||||
};
|
||||
|
||||
class FillStars3 : public FillRectilinear3
|
||||
{
|
||||
public:
|
||||
virtual Fill* clone() const { return new FillStars3(*this); };
|
||||
virtual ~FillStars3() {}
|
||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
virtual float _layer_angle(size_t /* idx */) const { return 0.f; }
|
||||
};
|
||||
|
||||
class FillCubic3 : public FillRectilinear3
|
||||
{
|
||||
public:
|
||||
virtual Fill* clone() const { return new FillCubic3(*this); };
|
||||
virtual ~FillCubic3() {}
|
||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
virtual float _layer_angle(size_t /* idx */) const { return 0.f; }
|
||||
};
|
||||
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
#endif // slic3r_FillRectilinear2_hpp_
|
|
@ -49,7 +49,7 @@ static inline bool is_ccw(const Polygon &poly)
|
|||
|
||||
// 1) Find the lowest lexicographical point.
|
||||
int imin = 0;
|
||||
for (size_t i = 1; i < poly.points.size(); ++ i) {
|
||||
for (int i = 1; i < poly.points.size(); ++ i) {
|
||||
const Point &pmin = poly.points[imin];
|
||||
const Point &p = poly.points[i];
|
||||
if (p.x < pmin.x || (p.x == pmin.x && p.y < pmin.y))
|
||||
|
|
300
xs/src/libslic3r/Int128.hpp
Normal file
300
xs/src/libslic3r/Int128.hpp
Normal file
|
@ -0,0 +1,300 @@
|
|||
// This is an excerpt of from the Clipper library by Angus Johnson, see the license below,
|
||||
// implementing a 64 x 64 -> 128bit multiply, and 128bit addition, subtraction and compare
|
||||
// operations, to be used with exact geometric predicates.
|
||||
// The code has been extended by Vojtech Bubnik to use 128 bit intrinsic types
|
||||
// and/or 64x64->128 intrinsic functions where possible.
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Author : Angus Johnson *
|
||||
* Version : 6.2.9 *
|
||||
* Date : 16 February 2015 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2015 *
|
||||
* *
|
||||
* License: *
|
||||
* Use, modification & distribution is subject to Boost Software License Ver 1. *
|
||||
* http://www.boost.org/LICENSE_1_0.txt *
|
||||
* *
|
||||
* Attributions: *
|
||||
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
|
||||
* "A generic solution to polygon clipping" *
|
||||
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
|
||||
* http://portal.acm.org/citation.cfm?id=129906 *
|
||||
* *
|
||||
* Computer graphics and geometric modeling: implementation and algorithms *
|
||||
* By Max K. Agoston *
|
||||
* Springer; 1 edition (January 4, 2005) *
|
||||
* http://books.google.com/books?q=vatti+clipping+agoston *
|
||||
* *
|
||||
* See also: *
|
||||
* "Polygon Offsetting by Computing Winding Numbers" *
|
||||
* Paper no. DETC2005-85513 pp. 565-575 *
|
||||
* ASME 2005 International Design Engineering Technical Conferences *
|
||||
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
|
||||
* September 24-28, 2005 , Long Beach, California, USA *
|
||||
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#define SLIC3R_DEBUG
|
||||
|
||||
// Make assert active if SLIC3R_DEBUG
|
||||
#ifdef SLIC3R_DEBUG
|
||||
#undef NDEBUG
|
||||
#define DEBUG
|
||||
#define _DEBUG
|
||||
#undef assert
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include "Point.hpp"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define HAS_INTRINSIC_128_TYPE
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Int128 class (enables safe math on signed 64bit integers)
|
||||
// eg Int128 val1((int64_t)9223372036854775807); //ie 2^63 -1
|
||||
// Int128 val2((int64_t)9223372036854775807);
|
||||
// Int128 val3 = val1 * val2;
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class Int128
|
||||
{
|
||||
|
||||
#ifdef HAS_INTRINSIC_128_TYPE
|
||||
|
||||
/******************************************** Using the intrinsic 128bit x 128bit multiply ************************************************/
|
||||
|
||||
public:
|
||||
__int128 value;
|
||||
|
||||
Int128(int64_t lo = 0) : value(lo) {}
|
||||
Int128(const Int128 &v) : value(v.value) {}
|
||||
|
||||
Int128& operator=(const int64_t &rhs) { value = rhs; return *this; }
|
||||
|
||||
uint64_t lo() const { return uint64_t(value); }
|
||||
int64_t hi() const { return int64_t(value >> 64); }
|
||||
int sign() const { return (value > 0) - (value < 0); }
|
||||
|
||||
bool operator==(const Int128 &rhs) const { return value == rhs.value; }
|
||||
bool operator!=(const Int128 &rhs) const { return value != rhs.value; }
|
||||
bool operator> (const Int128 &rhs) const { return value > rhs.value; }
|
||||
bool operator< (const Int128 &rhs) const { return value < rhs.value; }
|
||||
bool operator>=(const Int128 &rhs) const { return value >= rhs.value; }
|
||||
bool operator<=(const Int128 &rhs) const { return value <= rhs.value; }
|
||||
|
||||
Int128& operator+=(const Int128 &rhs) { value += rhs.value; return *this; }
|
||||
Int128 operator+ (const Int128 &rhs) const { return Int128(value + rhs.value); }
|
||||
Int128& operator-=(const Int128 &rhs) { value -= rhs.value; return *this; }
|
||||
Int128 operator -(const Int128 &rhs) const { return Int128(value - rhs.value); }
|
||||
Int128 operator -() const { return Int128(- value); }
|
||||
|
||||
operator double() const { return double(value); }
|
||||
|
||||
static inline Int128 multiply(int64_t lhs, int64_t rhs) { return Int128(__int128(lhs) * __int128(rhs)); }
|
||||
|
||||
// Evaluate signum of a 2x2 determinant.
|
||||
static int sign_determinant_2x2(int64_t a11, int64_t a12, int64_t a21, int64_t a22)
|
||||
{
|
||||
__int128 det = __int128(a11) * __int128(a22) - __int128(a12) * __int128(a21);
|
||||
return (det > 0) - (det < 0);
|
||||
}
|
||||
|
||||
// Compare two rational numbers.
|
||||
static int compare_rationals(int64_t p1, int64_t q1, int64_t p2, int64_t q2)
|
||||
{
|
||||
int invert = ((q1 < 0) == (q2 < 0)) ? 1 : -1;
|
||||
__int128 det = __int128(p1) * __int128(q2) - __int128(p2) * __int128(q1);
|
||||
return ((det > 0) - (det < 0)) * invert;
|
||||
}
|
||||
|
||||
#else /* HAS_INTRINSIC_128_TYPE */
|
||||
|
||||
/******************************************** Splitting the 128bit number into two 64bit words *********************************************/
|
||||
|
||||
Int128(int64_t lo = 0) : m_lo((uint64_t)lo), m_hi((lo < 0) ? -1 : 0) {}
|
||||
Int128(const Int128 &val) : m_lo(val.m_lo), m_hi(val.m_hi) {}
|
||||
Int128(const int64_t& hi, const uint64_t& lo) : m_lo(lo), m_hi(hi) {}
|
||||
|
||||
Int128& operator = (const int64_t &val)
|
||||
{
|
||||
m_lo = (uint64_t)val;
|
||||
m_hi = (val < 0) ? -1 : 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint64_t lo() const { return m_lo; }
|
||||
int64_t hi() const { return m_hi; }
|
||||
int sign() const { return (m_hi == 0) ? (m_lo > 0) : (m_hi > 0) - (m_hi < 0); }
|
||||
|
||||
bool operator == (const Int128 &val) const { return m_hi == val.m_hi && m_lo == val.m_lo; }
|
||||
bool operator != (const Int128 &val) const { return ! (*this == val); }
|
||||
bool operator > (const Int128 &val) const { return (m_hi == val.m_hi) ? m_lo > val.m_lo : m_hi > val.m_hi; }
|
||||
bool operator < (const Int128 &val) const { return (m_hi == val.m_hi) ? m_lo < val.m_lo : m_hi < val.m_hi; }
|
||||
bool operator >= (const Int128 &val) const { return ! (*this < val); }
|
||||
bool operator <= (const Int128 &val) const { return ! (*this > val); }
|
||||
|
||||
Int128& operator += (const Int128 &rhs)
|
||||
{
|
||||
m_hi += rhs.m_hi;
|
||||
m_lo += rhs.m_lo;
|
||||
if (m_lo < rhs.m_lo) m_hi++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 operator + (const Int128 &rhs) const
|
||||
{
|
||||
Int128 result(*this);
|
||||
result+= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
Int128& operator -= (const Int128 &rhs)
|
||||
{
|
||||
*this += -rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Int128 operator - (const Int128 &rhs) const
|
||||
{
|
||||
Int128 result(*this);
|
||||
result -= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
Int128 operator-() const { return (m_lo == 0) ? Int128(-m_hi, 0) : Int128(~m_hi, ~m_lo + 1); }
|
||||
|
||||
operator double() const
|
||||
{
|
||||
const double shift64 = 18446744073709551616.0; //2^64
|
||||
return (m_hi < 0) ?
|
||||
((m_lo == 0) ?
|
||||
(double)m_hi * shift64 :
|
||||
-(double)(~m_lo + ~m_hi * shift64)) :
|
||||
(double)(m_lo + m_hi * shift64);
|
||||
}
|
||||
|
||||
static inline Int128 multiply(int64_t lhs, int64_t rhs)
|
||||
{
|
||||
#if defined(_MSC_VER) && defined(_WIN64)
|
||||
// On Visual Studio 64bit, use the _mul128() intrinsic function.
|
||||
Int128 result;
|
||||
result.m_lo = (uint64_t)_mul128(lhs, rhs, &result.m_hi);
|
||||
return result;
|
||||
#else
|
||||
// This branch should only be executed in case there is neither __int16 type nor _mul128 intrinsic
|
||||
// function available. This is mostly on 32bit operating systems.
|
||||
// Use a pure C implementation of _mul128().
|
||||
|
||||
int negate = (lhs < 0) != (rhs < 0);
|
||||
|
||||
if (lhs < 0)
|
||||
lhs = -lhs;
|
||||
uint64_t int1Hi = uint64_t(lhs) >> 32;
|
||||
uint64_t int1Lo = uint64_t(lhs & 0xFFFFFFFF);
|
||||
|
||||
if (rhs < 0)
|
||||
rhs = -rhs;
|
||||
uint64_t int2Hi = uint64_t(rhs) >> 32;
|
||||
uint64_t int2Lo = uint64_t(rhs & 0xFFFFFFFF);
|
||||
|
||||
//because the high (sign) bits in both int1Hi & int2Hi have been zeroed,
|
||||
//there's no risk of 64 bit overflow in the following assignment
|
||||
//(ie: $7FFFFFFF*$FFFFFFFF + $7FFFFFFF*$FFFFFFFF < 64bits)
|
||||
uint64_t a = int1Hi * int2Hi;
|
||||
uint64_t b = int1Lo * int2Lo;
|
||||
//Result = A shl 64 + C shl 32 + B ...
|
||||
uint64_t c = int1Hi * int2Lo + int1Lo * int2Hi;
|
||||
|
||||
Int128 tmp;
|
||||
tmp.m_hi = int64_t(a + (c >> 32));
|
||||
tmp.m_lo = int64_t(c << 32);
|
||||
tmp.m_lo += int64_t(b);
|
||||
if (tmp.m_lo < b)
|
||||
++ tmp.m_hi;
|
||||
if (negate)
|
||||
tmp = - tmp;
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Evaluate signum of a 2x2 determinant.
|
||||
static int sign_determinant_2x2(int64_t a11, int64_t a12, int64_t a21, int64_t a22)
|
||||
{
|
||||
return (Int128::multiply(a11, a22) - Int128::multiply(a12, a21)).sign();
|
||||
}
|
||||
|
||||
// Compare two rational numbers.
|
||||
static int compare_rationals(int64_t p1, int64_t q1, int64_t p2, int64_t q2)
|
||||
{
|
||||
int invert = ((q1 < 0) == (q2 < 0)) ? 1 : -1;
|
||||
Int128 det = Int128::multiply(p1, q2) - Int128::multiply(p2, q1);
|
||||
return det.sign() * invert;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_lo;
|
||||
int64_t m_hi;
|
||||
|
||||
|
||||
#endif /* HAS_INTRINSIC_128_TYPE */
|
||||
|
||||
|
||||
/******************************************** Common methods ************************************************/
|
||||
|
||||
public:
|
||||
|
||||
// Evaluate signum of a 2x2 determinant, use a numeric filter to avoid 128 bit multiply if possible.
|
||||
static int sign_determinant_2x2_filtered(int64_t a11, int64_t a12, int64_t a21, int64_t a22)
|
||||
{
|
||||
// First try to calculate the determinant over the upper 31 bits.
|
||||
// Round p1, p2, q1, q2 to 31 bits.
|
||||
int64_t a11s = (a11 + (1 << 31)) >> 32;
|
||||
int64_t a12s = (a12 + (1 << 31)) >> 32;
|
||||
int64_t a21s = (a21 + (1 << 31)) >> 32;
|
||||
int64_t a22s = (a22 + (1 << 31)) >> 32;
|
||||
// Result fits 63 bits, it is an approximate of the determinant divided by 2^64.
|
||||
int64_t det = a11s * a22s - a12s * a21s;
|
||||
// Maximum absolute of the remainder of the exact determinant, divided by 2^64.
|
||||
int64_t err = ((std::abs(a11s) + std::abs(a12s) + std::abs(a21s) + std::abs(a22s)) << 1) + 1;
|
||||
assert(std::abs(det) <= err || ((det > 0) ? 1 : -1) == sign_determinant_2x2(a11, a12, a21, a22));
|
||||
return (std::abs(det) > err) ?
|
||||
((det > 0) ? 1 : -1) :
|
||||
sign_determinant_2x2(a11, a12, a21, a22);
|
||||
}
|
||||
|
||||
// Compare two rational numbers, use a numeric filter to avoid 128 bit multiply if possible.
|
||||
static int compare_rationals_filtered(int64_t p1, int64_t q1, int64_t p2, int64_t q2)
|
||||
{
|
||||
// First try to calculate the determinant over the upper 31 bits.
|
||||
// Round p1, p2, q1, q2 to 31 bits.
|
||||
int invert = ((q1 < 0) == (q2 < 0)) ? 1 : -1;
|
||||
int64_t q1s = (q1 + (1 << 31)) >> 32;
|
||||
int64_t q2s = (q2 + (1 << 31)) >> 32;
|
||||
if (q1s != 0 && q2s != 0) {
|
||||
int64_t p1s = (p1 + (1 << 31)) >> 32;
|
||||
int64_t p2s = (p2 + (1 << 31)) >> 32;
|
||||
// Result fits 63 bits, it is an approximate of the determinant divided by 2^64.
|
||||
int64_t det = p1s * q2s - p2s * q1s;
|
||||
// Maximum absolute of the remainder of the exact determinant, divided by 2^64.
|
||||
int64_t err = ((std::abs(p1s) + std::abs(q1s) + std::abs(p2s) + std::abs(q2s)) << 1) + 1;
|
||||
assert(std::abs(det) <= err || ((det > 0) ? 1 : -1) * invert == compare_rationals(p1, q1, p2, q2));
|
||||
if (std::abs(det) > err)
|
||||
return ((det > 0) ? 1 : -1) * invert;
|
||||
}
|
||||
return sign_determinant_2x2(p1, q1, p2, q2);
|
||||
}
|
||||
|
||||
// Exact orientation predicate,
|
||||
// returns +1: CCW, 0: collinear, -1: CW.
|
||||
static int orient(const Slic3r::Point &p1, const Slic3r::Point &p2, const Slic3r::Point &p3)
|
||||
{
|
||||
Slic3r::Vector v1(p2 - p1);
|
||||
Slic3r::Vector v2(p3 - p1);
|
||||
return sign_determinant_2x2_filtered(v1.x, v1.y, v2.x, v2.y);
|
||||
}
|
||||
};
|
|
@ -74,7 +74,10 @@ public:
|
|||
void export_region_slices_to_svg_debug(const char *name);
|
||||
void export_region_fill_surfaces_to_svg_debug(const char *name);
|
||||
|
||||
private:
|
||||
// Is there any valid extrusion assigned to this LayerRegion?
|
||||
bool has_extrusions() const { return ! this->perimeters.entities.empty() || ! this->fills.entities.empty(); }
|
||||
|
||||
private:
|
||||
Layer *_layer;
|
||||
PrintRegion *_region;
|
||||
|
||||
|
@ -131,7 +134,10 @@ public:
|
|||
// Export to "out/LayerRegion-name-%d.svg" with an increasing index with every export.
|
||||
void export_region_slices_to_svg_debug(const char *name);
|
||||
void export_region_fill_surfaces_to_svg_debug(const char *name);
|
||||
|
||||
|
||||
// Is there any valid extrusion assigned to this LayerRegion?
|
||||
virtual bool has_extrusions() const { for (auto layerm : this->regions) if (layerm->has_extrusions()) return true; return false; }
|
||||
|
||||
protected:
|
||||
size_t _id; // sequential number of layer, 0-based
|
||||
PrintObject *_object;
|
||||
|
@ -152,6 +158,9 @@ public:
|
|||
// Extrusion paths for the support base and for the support interface and contacts.
|
||||
ExtrusionEntityCollection support_fills;
|
||||
|
||||
// Is there any valid extrusion assigned to this LayerRegion?
|
||||
virtual bool has_extrusions() const { return ! support_fills.empty(); }
|
||||
|
||||
protected:
|
||||
SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
|
||||
Layer(id, object, height, print_z, slice_z) {}
|
||||
|
|
|
@ -88,12 +88,6 @@ Point::nearest_point_index(const Points &points) const
|
|||
return this->nearest_point_index(p);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T sqr(const T x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
int Point::nearest_point_index(const PointConstPtrs &points) const
|
||||
{
|
||||
int idx = -1;
|
||||
|
|
|
@ -27,7 +27,8 @@ typedef std::vector<Pointf3> Pointf3s;
|
|||
|
||||
class Point
|
||||
{
|
||||
public:
|
||||
public:
|
||||
typedef coord_t coord_type;
|
||||
coord_t x;
|
||||
coord_t y;
|
||||
Point(coord_t _x = 0, coord_t _y = 0): x(_x), y(_y) {};
|
||||
|
@ -77,6 +78,7 @@ class Point
|
|||
inline Point operator+(const Point& point1, const Point& point2) { return Point(point1.x + point2.x, point1.y + point2.y); }
|
||||
inline Point operator-(const Point& point1, const Point& point2) { return Point(point1.x - point2.x, point1.y - point2.y); }
|
||||
inline Point operator*(double scalar, const Point& point2) { return Point(scalar * point2.x, scalar * point2.y); }
|
||||
inline int64_t cross(const Point &v1, const Point &v2) { return int64_t(v1.x) * int64_t(v2.y) - int64_t(v1.y) * int64_t(v2.x); }
|
||||
|
||||
// To be used by std::unordered_map, std::unordered_multimap and friends.
|
||||
struct PointHash {
|
||||
|
@ -189,6 +191,7 @@ std::ostream& operator<<(std::ostream &stm, const Pointf &pointf);
|
|||
class Pointf
|
||||
{
|
||||
public:
|
||||
typedef coordf_t coord_type;
|
||||
coordf_t x;
|
||||
coordf_t y;
|
||||
explicit Pointf(coordf_t _x = 0, coordf_t _y = 0): x(_x), y(_y) {};
|
||||
|
@ -239,6 +242,11 @@ class Pointf3 : public Pointf
|
|||
Vectorf3 vector_to(const Pointf3 &point) const;
|
||||
};
|
||||
|
||||
template<typename TO> inline TO convert_to(const Point &src) { return TO(TO::coord_type(src.x), TO::coord_type(src.y)); }
|
||||
template<typename TO> inline TO convert_to(const Pointf &src) { return TO(TO::coord_type(src.x), TO::coord_type(src.y)); }
|
||||
template<typename TO> inline TO convert_to(const Point3 &src) { return TO(TO::coord_type(src.x), TO::coord_type(src.y), TO::coord_type(src.z)); }
|
||||
template<typename TO> inline TO convert_to(const Pointf3 &src) { return TO(TO::coord_type(src.x), TO::coord_type(src.y), TO::coord_type(src.z)); }
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
// start Boost
|
||||
|
|
|
@ -9,11 +9,6 @@ struct Chaining
|
|||
size_t idx;
|
||||
};
|
||||
|
||||
#ifndef sqr
|
||||
template<typename T>
|
||||
inline T sqr(T x) { return x * x; }
|
||||
#endif /* sqr */
|
||||
|
||||
template<typename T>
|
||||
inline int nearest_point_index(const std::vector<Chaining> &pairs, const Point &start_near, bool no_reverse)
|
||||
{
|
||||
|
@ -49,11 +44,8 @@ inline int nearest_point_index(const std::vector<Chaining> &pairs, const Point &
|
|||
Polylines PolylineCollection::_chained_path_from(
|
||||
const Polylines &src,
|
||||
Point start_near,
|
||||
bool no_reverse
|
||||
#if SLIC3R_CPPVER >= 11
|
||||
, bool move_from_src
|
||||
#endif
|
||||
)
|
||||
bool no_reverse,
|
||||
bool move_from_src)
|
||||
{
|
||||
std::vector<Chaining> endpoints;
|
||||
endpoints.reserve(src.size());
|
||||
|
@ -70,15 +62,11 @@ Polylines PolylineCollection::_chained_path_from(
|
|||
// find nearest point
|
||||
int endpoint_index = nearest_point_index<double>(endpoints, start_near, no_reverse);
|
||||
assert(endpoint_index >= 0 && endpoint_index < endpoints.size() * 2);
|
||||
#if SLIC3R_CPPVER > 11
|
||||
if (move_from_src) {
|
||||
retval.push_back(std::move(src[endpoints[endpoint_index/2].idx]));
|
||||
} else {
|
||||
retval.push_back(src[endpoints[endpoint_index/2].idx]);
|
||||
}
|
||||
#else
|
||||
retval.push_back(src[endpoints[endpoint_index/2].idx]);
|
||||
#endif
|
||||
if (endpoint_index & 1)
|
||||
retval.back().reverse();
|
||||
endpoints.erase(endpoints.begin() + endpoint_index/2);
|
||||
|
@ -87,40 +75,6 @@ Polylines PolylineCollection::_chained_path_from(
|
|||
return retval;
|
||||
}
|
||||
|
||||
#if SLIC3R_CPPVER >= 11
|
||||
Polylines PolylineCollection::chained_path(Polylines &&src, bool no_reverse)
|
||||
{
|
||||
return (src.empty() || src.front().points.empty()) ?
|
||||
Polylines() :
|
||||
_chained_path_from(src, src.front().first_point(), no_reverse, true);
|
||||
}
|
||||
|
||||
Polylines PolylineCollection::chained_path_from(Polylines &&src, Point start_near, bool no_reverse)
|
||||
{
|
||||
return _chained_path_from(src, start_near, no_reverse, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
Polylines PolylineCollection::chained_path(const Polylines &src, bool no_reverse)
|
||||
{
|
||||
return (src.empty() || src.front().points.empty()) ?
|
||||
Polylines() :
|
||||
_chained_path_from(src, src.front().first_point(), no_reverse
|
||||
#if SLIC3R_CPPVER >= 11
|
||||
, false
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
Polylines PolylineCollection::chained_path_from(const Polylines &src, Point start_near, bool no_reverse)
|
||||
{
|
||||
return _chained_path_from(src, start_near, no_reverse
|
||||
#if SLIC3R_CPPVER >= 11
|
||||
, false
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
Point PolylineCollection::leftmost_point(const Polylines &polylines)
|
||||
{
|
||||
if (polylines.empty()) CONFESS("leftmost_point() called on empty PolylineCollection");
|
||||
|
@ -134,10 +88,4 @@ Point PolylineCollection::leftmost_point(const Polylines &polylines)
|
|||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
PolylineCollection::append(const Polylines &pp)
|
||||
{
|
||||
this->polylines.insert(this->polylines.end(), pp.begin(), pp.end());
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -11,11 +11,8 @@ class PolylineCollection
|
|||
static Polylines _chained_path_from(
|
||||
const Polylines &src,
|
||||
Point start_near,
|
||||
bool no_reverse
|
||||
#if SLIC3R_CPPVER >= 11
|
||||
, bool move_from_src
|
||||
#endif
|
||||
);
|
||||
bool no_reverse,
|
||||
bool move_from_src);
|
||||
|
||||
public:
|
||||
Polylines polylines;
|
||||
|
@ -25,15 +22,24 @@ public:
|
|||
{ retval->polylines = chained_path_from(this->polylines, start_near, no_reverse); }
|
||||
Point leftmost_point() const
|
||||
{ return leftmost_point(polylines); }
|
||||
void append(const Polylines &polylines);
|
||||
void append(const Polylines &polylines)
|
||||
{ this->polylines.insert(this->polylines.end(), polylines.begin(), polylines.end()); }
|
||||
|
||||
static Point leftmost_point(const Polylines &polylines);
|
||||
#if SLIC3R_CPPVER >= 11
|
||||
static Polylines chained_path(Polylines &&src, bool no_reverse = false);
|
||||
static Polylines chained_path_from(Polylines &&src, Point start_near, bool no_reverse = false);
|
||||
#endif
|
||||
static Polylines chained_path(const Polylines &src, bool no_reverse = false);
|
||||
static Polylines chained_path_from(const Polylines &src, Point start_near, bool no_reverse = false);
|
||||
static Polylines chained_path(Polylines &&src, bool no_reverse = false) {
|
||||
return (src.empty() || src.front().points.empty()) ?
|
||||
Polylines() :
|
||||
_chained_path_from(src, src.front().first_point(), no_reverse, true);
|
||||
}
|
||||
static Polylines chained_path_from(Polylines &&src, Point start_near, bool no_reverse = false)
|
||||
{ return _chained_path_from(src, start_near, no_reverse, true); }
|
||||
static Polylines chained_path(const Polylines &src, bool no_reverse = false) {
|
||||
return (src.empty() || src.front().points.empty()) ?
|
||||
Polylines() :
|
||||
_chained_path_from(src, src.front().first_point(), no_reverse, false);
|
||||
}
|
||||
static Polylines chained_path_from(const Polylines &src, Point start_near, bool no_reverse = false)
|
||||
{ return _chained_path_from(src, start_near, no_reverse, false); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -202,6 +202,7 @@ public:
|
|||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
UNUSED(create);
|
||||
OPT_PTR(clip_multipart_objects);
|
||||
OPT_PTR(dont_support_bridges);
|
||||
OPT_PTR(elefant_foot_compensation);
|
||||
|
@ -283,6 +284,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
|
|||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
UNUSED(create);
|
||||
OPT_PTR(bottom_solid_layers);
|
||||
OPT_PTR(bridge_flow_ratio);
|
||||
OPT_PTR(bridge_speed);
|
||||
|
@ -369,6 +371,7 @@ public:
|
|||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
UNUSED(create);
|
||||
OPT_PTR(before_layer_gcode);
|
||||
OPT_PTR(deretract_speed);
|
||||
OPT_PTR(end_gcode);
|
||||
|
@ -571,6 +574,7 @@ public:
|
|||
}
|
||||
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) {
|
||||
UNUSED(create);
|
||||
OPT_PTR(octoprint_host);
|
||||
OPT_PTR(octoprint_apikey);
|
||||
OPT_PTR(serial_port);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <limits>
|
||||
|
||||
#include "libslic3r.h"
|
||||
#include "Slicing.hpp"
|
||||
#include "SlicingAdaptive.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
|
@ -308,19 +309,6 @@ std::vector<coordf_t> layer_height_profile_adaptive(
|
|||
return layer_height_profile;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T clamp(const T low, const T high, const T value)
|
||||
{
|
||||
return std::max(low, std::min(high, value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T lerp(const T a, const T b, const T t)
|
||||
{
|
||||
assert(t >= T(-EPSILON) && t <= T(1.+EPSILON));
|
||||
return (1. - t) * a + t * b;
|
||||
}
|
||||
|
||||
void adjust_layer_height_profile(
|
||||
const SlicingParameters &slicing_params,
|
||||
std::vector<coordf_t> &layer_height_profile,
|
||||
|
|
|
@ -88,6 +88,10 @@ inline std::string debug_out_path(const char *name, ...)
|
|||
#define PRINTF_ZU "%zu"
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) (void)(x)
|
||||
#endif /* UNUSED */
|
||||
|
||||
// Write slices as SVG images into out directory during the 2D processing of the slices.
|
||||
// #define SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
|
||||
|
@ -142,6 +146,25 @@ inline std::unique_ptr<T> make_unique(Args&&... args) {
|
|||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline T sqr(T x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T clamp(const T low, const T high, const T value)
|
||||
{
|
||||
return std::max(low, std::min(high, value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T lerp(const T a, const T b, const T t)
|
||||
{
|
||||
assert(t >= T(-EPSILON) && t <= T(1.+EPSILON));
|
||||
return (1. - t) * a + t * b;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue