mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-21 15:51:10 -06:00
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue