//////////////////////////////////////////////////////////////////// // Types.h // // Copyright 2007 cDc@seacave // Distributed under the Boost Software License, Version 1.0 // (See http://www.boost.org/LICENSE_1_0.txt) #ifndef __SEACAVE_TYPES_H__ #define __SEACAVE_TYPES_H__ // I N C L U D E S ///////////////////////////////////////////////// #ifdef _MSC_VER #include #include #else #include #include #include #include #include #include #include #include #include #include #include #endif #ifdef _SUPPORT_CPP11 #ifdef __clang__ #include #else #include #endif #include #include #include #else #include #endif #ifdef _SUPPORT_CPP17 #if !defined(__GNUC__) || (__GNUC__ > 7) #include #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _USE_OPENMP #include #endif // Function delegate functionality #ifdef _SUPPORT_CPP11 #include "FastDelegateCPP11.h" #define DELEGATE fastdelegate::delegate #define DELEGATEBIND(DLGT, FNC) DLGT::from< FNC >() #define DELEGATEBINDCLASS(DLGT, FNC, OBJ) DLGT::from(*OBJ, FNC) #else #include "FastDelegate.h" #include "FastDelegateBind.h" #define DELEGATE fastdelegate::FastDelegate #define DELEGATEBIND(DLGT, FNC) fastdelegate::bind(FNC) #define DELEGATEBINDCLASS(DLGT, FNC, OBJ) fastdelegate::bind(FNC, OBJ) #endif // include usual boost libraries #ifdef _USE_BOOST #if 1 // disable exception support #define BOOST_NO_UNREACHABLE_RETURN_DETECTION #define BOOST_EXCEPTION_DISABLE #define BOOST_NO_EXCEPTIONS #endif #ifdef BOOST_NO_EXCEPTIONS #include #endif #define BOOST_NO_UNREACHABLE_RETURN_DETECTION // include headers that implement serialization support #include #include #include #include #include #include #include #include #if (BOOST_VERSION / 100000) > 1 || (BOOST_VERSION / 100 % 1000) > 55 #include #include #endif #include // include headers that define an input and output archive #include #include // include headers that define memory pools #include #include #endif #ifdef _USE_EIGEN #if defined(_MSC_VER) #pragma warning (push) #pragma warning (disable : 4244) // 'argument': conversion from '__int64' to 'int', possible loss of data #endif #include #include #include #include #include #include #include #include #if defined(_MSC_VER) #pragma warning (pop) #endif #endif #pragma push_macro("free") #undef free #pragma push_macro("DEBUG") #undef DEBUG #include #if CV_MAJOR_VERSION > 2 || CV_MINOR_VERSION > 3 #include #endif #include #ifdef HAVE_OPENCV_GPU #if CV_MAJOR_VERSION > 2 #include namespace cv { namespace gpu = cuda; } #else #include #endif #endif #pragma pop_macro("DEBUG") #pragma pop_macro("free") #ifdef _USE_SSE #include #include #endif // D E F I N E S /////////////////////////////////////////////////// // In order to create a singleton class // add this define in your class; #define DECLARE_SINGLETON(SClass) \ protected: SClass(); SClass(const SClass&); \ public: static inline SClass& GetInstance() { static SClass instance; return instance; } // or add this define and declare GetInstance() method in the .cpp // so that the singleton is unique even across modules; #define DEFINE_SINGLETON(SClass) \ protected: SClass(); SClass(const SClass&); \ public: static SClass& GetInstance(); // or add this declare ms_pInstance; #define DECLARE_SINGLETONPTR(SClass) \ SClass* SClass::ms_pInstance(NULL); \ SClass*& SClass::GetInstanceRef() { return ms_pInstance; } \ SClass* SClass::GetInstancePtr() { ASSERT(ms_pInstance); return ms_pInstance; } \ SClass& SClass::GetInstance() { ASSERT(ms_pInstance); return *ms_pInstance; } // and this define in the class definition. #define DEFINE_SINGLETONPTR(SClass) \ protected: SClass(); SClass(const SClass&); static SClass* ms_pInstance; \ public: static SClass*& GetInstanceRef(); \ public: static SClass* GetInstancePtr(); \ public: static SClass& GetInstance(); #ifndef CALL_MEMBER_FN #define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) #endif #ifndef __PROCESS__ # ifdef _MSC_VER # define __PROCESS__ ((unsigned)GetCurrentProcessId()) # else # define __PROCESS__ ((unsigned)getpid()) # endif #endif #ifndef __THREAD__ # ifdef _MSC_VER # define __THREAD__ ((unsigned)GetCurrentThreadId()) # elif defined(__APPLE__) # include inline pid_t GetCurrentThreadId() { uint64_t tid64; pthread_threadid_np(NULL, &tid64); return (pid_t)tid64; } # define __THREAD__ ((unsigned)GetCurrentThreadId()) # else # include # define __THREAD__ ((unsigned)((pid_t)syscall(SYS_gettid))) # endif #endif #ifndef STCALL # if defined(_MSC_VER) # define STCALL __cdecl # elif defined(__OS2__) # if defined (__GNUC__) && __GNUC__ < 4 # define STCALL _cdecl # else # /* On other compilers on OS/2, we use the _System calling convention */ # /* to be compatible with every compiler */ # define STCALL _System # endif # elif defined(__GNUC__) # define STCALL __attribute__((__cdecl__)) # else # define STCALL # endif #endif // STCALL // T Y P E D E F I N E S ///////////////////////////////////////// // // Type defines #ifndef _MSC_VER typedef int32_t HRESULT; typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef uint64_t QWORD; typedef char CHAR; typedef CHAR* LPSTR; typedef const CHAR* LPCSTR; typedef CHAR TCHAR; typedef LPSTR LPTSTR; typedef LPCSTR LPCTSTR; #define _tcslen strlen #define _tcscpy strcpy #define _tcsncpy strncpy #define _tcschr strchr #define _tcsrchr strrchr #define _tcscmp strcmp #define _tcsncmp strncmp #define _tcsicmp strcasecmp #define _tcsnicmp strncasecmp #define _tcsncicmp(s1,s2,s) strncasecmp(s1, s2, (s)*sizeof(TCHAR)) #define _stprintf sprintf #define _sntprintf snprintf #define _vsntprintf vsnprintf #define _vsctprintf _vscprintf int _vscprintf(LPCSTR format, va_list pargs); #define _T(s) s #endif //_MSC_VER #define DECLARE_NO_INDEX(...) std::numeric_limits<__VA_ARGS__>::max() #ifndef MAKEWORD #define MAKEWORD(a, b) ((WORD)(((BYTE)(((DWORD)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD)(b)) & 0xff))) << 8)) #endif #ifndef MAKELONG #define MAKELONG(a, b) ((DWORD)(((WORD)(((DWORD)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD)(b)) & 0xffff))) << 16)) #endif #ifndef LOWORD #define LOWORD(l) ((WORD)(((DWORD)(l)) & 0xffff)) #endif #ifndef HIWORD #define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xffff)) #endif #ifndef LOBYTE #define LOBYTE(w) ((BYTE)(((WORD)(w)) & 0xff)) #endif #ifndef HIBYTE #define HIBYTE(w) ((BYTE)((((WORD)(w)) >> 8) & 0xff)) #endif #ifndef MAX_PATH #define MAX_PATH 260 #endif #ifndef NULL #define NULL 0 #endif #ifdef max #undef max #endif #ifdef min #undef min #endif #ifndef MINF #define MINF std::min #endif #ifndef MAXF #define MAXF std::max #endif #ifndef RAND #define RAND std::rand #endif namespace SEACAVE { // signed and unsigned types of the size of the architecture // (32 or 64 bit for x86 and respectively x64) #ifdef _ENVIRONMENT64 typedef int64_t int_t; typedef uint64_t uint_t; #else typedef int32_t int_t; typedef uint32_t uint_t; #endif // type used for the size of the files typedef int64_t size_f_t; // type used as the default floating number precision typedef double REAL; // invalid index constexpr uint32_t NO_ID = DECLARE_NO_INDEX(uint32_t); template struct RealType { typedef typename std::conditional::value, TYPE, REALTYPE>::type type; }; template inline T MINF3(const T& x1, const T& x2, const T& x3) { return MINF(MINF(x1, x2), x3); } template inline T MAXF3(const T& x1, const T& x2, const T& x3) { return MAXF(MAXF(x1, x2), x3); } template FORCEINLINE T RANDOM() { return T(RAND())/RAND_MAX; } template union TAliasCast { T1 f; T2 i; inline TAliasCast() {} inline TAliasCast(T1 v) : f(v) {} inline TAliasCast(T2 v) : i(v) {} inline TAliasCast& operator = (T1 v) { f = v; return *this; } inline TAliasCast& operator = (T2 v) { i = v; return *this; } inline operator T1 () const { return f; } }; typedef TAliasCast CastF2I; typedef TAliasCast CastD2I; } // namespace SEACAVE #if defined(_MSC_VER) # define __LITTLE_ENDIAN 0 # define __BIG_ENDIAN 1 # define __PDP_ENDIAN 2 # define __BYTE_ORDER __LITTLE_ENDIAN #elif defined(__APPLE__) # include #elif defined(__GNUC__) # include #endif // I N C L U D E S ///////////////////////////////////////////////// #include "Strings.h" #include "AutoPtr.h" #include "List.h" #include "Thread.h" #include "SharedPtr.h" #include "Queue.h" #include "Hash.h" #include "Timer.h" #include "CriticalSection.h" #include "Semaphore.h" #include "Util.h" #include "File.h" #include "MemFile.h" #include "LinkLib.h" namespace SEACAVE { typedef class GENERAL_API CSharedPtr FilePtr; typedef class GENERAL_API CSharedPtr ISTREAMPTR; typedef ISTREAM* LPISTREAM; typedef class GENERAL_API CSharedPtr OSTREAMPTR; typedef OSTREAM* LPOSTREAM; typedef class GENERAL_API CSharedPtr IOSTREAMPTR; typedef IOSTREAM* LPIOSTREAM; typedef class GENERAL_API cList VoidArr; typedef class GENERAL_API cList LPCTSTRArr; typedef class GENERAL_API cList StringArr; typedef class GENERAL_API cList IDXArr; typedef class GENERAL_API cList Unsigned8Arr; typedef class GENERAL_API cList UnsignedArr; typedef class GENERAL_API cList Unsigned32Arr; typedef class GENERAL_API cList Unsigned64Arr; typedef class GENERAL_API cList SizeArr; typedef class GENERAL_API cList IntArr; typedef class GENERAL_API cList BoolArr; typedef class GENERAL_API cList FloatArr; typedef class GENERAL_API cList DoubleArr; } // namespace SEACAVE #include "Log.h" #include "EventQueue.h" #include "SML.h" #include "ConfigTable.h" #include "HTMLDoc.h" // D E F I N E S /////////////////////////////////////////////////// // // Constant defines // everything went smooth #define _OK ((HRESULT)0L) // just reports no errors #define _CANCEL 0x82000000 // general error message #define _FAIL 0x82000001 // specific error messages #define _CREATEAPI 0x82000002 #define _CREATEDEVICE 0x82000003 #define _CREATEBUFFER 0x82000004 #define _INVALIDPARAM 0x82000005 #define _INVALIDID 0x82000006 #define _BUFFERSIZE 0x82000007 #define _BUFFERLOCK 0x82000008 #define _NOTCOMPATIBLE 0x82000009 #define _OUTOFMEMORY 0x8200000a #define _FILENOTFOUND 0x8200000b #define _INVALIDFILE 0x8200000c #define _NOSHADERSUPPORT 0x8200000d #define _NOSERVERFOUND 0x8200000e #define _WOULDBLOCK 0x8200000f #ifndef SUCCEEDED #define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) #endif #ifndef FAILED #define FAILED(hr) (((HRESULT)(hr)) < 0) #endif // D E F I N E S /////////////////////////////////////////////////// #define RGBA(r, g, b, a) ((DWORD)(((a) << 24) | ((r) << 16) | ((g) << 8) | (b))) #define RGBC(clr) (RGBA((BYTE)((clr).fR*255), (BYTE)((clr).fG*255), (BYTE)((clr).fB*255), (BYTE)((clr).fA*255))) #define RGB24TO8(r,g,b) ((BYTE)((((WORD)r)*30+((WORD)g)*59+((WORD)b)*11)/100)) #define RGB24TO16(r,g,b) ((((WORD)(((BYTE)(r))>>3))<<11) | (((WORD)(((BYTE)(g))>>2))<<5) | ((WORD)(((BYTE)(b))>>3))) #define RGB16TOR(rgb) (((BYTE)(((WORD)(rgb))>>11))<<3) #define RGB16TOG(rgb) (((BYTE)((((WORD)(rgb))&0x07E0)>>5))<<2) #define RGB16TOB(rgb) (((BYTE)(((WORD)(rgb))&0x001F))<<3) #define TIMER_START() SEACAVE::Timer::SysType timerStart = SEACAVE::Timer::GetSysTime() #define TIMER_UPDATE() timerStart = SEACAVE::Timer::GetSysTime() #define TIMER_GET() SEACAVE::Timer::SysTime2TimeMs(SEACAVE::Timer::GetSysTime() - timerStart) #define TIMER_GET_INT() ((SEACAVE::Timer::SysType)TIMER_GET()) #define TIMER_GET_FORMAT() SEACAVE::Util::formatTime(TIMER_GET_INT()) // D E F I N E S /////////////////////////////////////////////////// #ifndef CHECK #define CHECK(exp) { if (!(exp)) { VERBOSE("Check failed: " #exp); abort(); } } #endif #ifndef ABORT #define ABORT(msg) { VERBOSE("error: " #msg); exit(-1); } #endif #ifndef _USE_MATH_DEFINES /** e */ #ifndef M_E #define M_E 2.7182818284590452353602874713527 #endif /** ln(2) */ #ifndef M_LN2 #define M_LN2 0.69314718055994530941723212145818 #endif /** ln(10) */ #ifndef M_LN10 #define M_LN10 2.3025850929940456840179914546844 #endif /** pi */ #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif /** pi/2 */ #ifndef M_PI_2 #define M_PI_2 1.5707963267948966192313216916398 #endif /** 1/pi */ #ifndef M_1_PI #define M_1_PI 0.31830988618379067153776752674503 #endif /** 2/pi */ #ifndef M_2_PI #define M_2_PI 0.63661977236758134307553505349006 #endif /** 2*sqrt(pi) */ #ifndef M_2_SQRTPI #define M_2_SQRTPI 1.1283791670955125738961589031216 #endif /** sqrt(2) */ #ifndef M_SQRT2 #define M_SQRT2 1.4142135623730950488016887242097 #endif /** sqrt(1/2) */ #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440084436210485 #endif #endif // constants #define TWO_PI 6.283185307179586476925286766559 #define PI 3.1415926535897932384626433832795 #define HALF_PI 1.5707963267948966192313216916398 #define SQRT_2PI 2.506628274631000502415765284811 #define INV_TWO_PI 0.15915494309189533576888376337251 #define INV_PI 0.31830988618379067153776752674503 #define INV_HALF_PI 0.63661977236758134307553505349006 #define INV_SQRT_2PI 0.39894228040143267793994605993439 #define D2R(d) ((d)*(PI/180.0)) // degree to radian #define R2D(r) ((r)*(180.0/PI)) // radian to degree #define SQRT_2 1.4142135623730950488016887242097 #define SQRT_3 1.7320508075688772935274463415059 #define LOG_2 0.30102999566398119521373889472449 #define LN_2 0.69314718055994530941723212145818 #define ZERO_TOLERANCE (1e-7) #define INV_ZERO (1e+14) // float constants #define FTWO_PI ((float)TWO_PI) #define FPI ((float)PI) #define FHALF_PI ((float)HALF_PI) #define FSQRT_2PI ((float)SQRT_2PI) #define FINV_TWO_PI ((float)INV_TWO_PI) #define FINV_PI ((float)INV_PI) #define FINV_HALF_PI ((float)INV_HALF_PI) #define FINV_SQRT_2PI ((float)INV_SQRT_2PI) #define FD2R(d) ((d)*(FPI/180.f)) // degree to radian #define FR2D(r) ((r)*(180.f/FPI)) // radian to degree #define FSQRT_2 ((float)SQRT_2) #define FSQRT_3 ((float)SQRT_3) #define FLOG_2 ((float)LOG_2) #define FLN_2 ((float)LN_2) #define FZERO_TOLERANCE 0.0001f #define FINV_ZERO 1000000.f #define GCLASS unsigned #define FRONT 0 #define BACK 1 #define PLANAR 2 #define CLIPPED 3 #define CULLED 4 #define VISIBLE 5 // M A C R O S ///////////////////////////////////////////////////// #define FLOOR SEACAVE::Floor2Int #define FLOOR2INT SEACAVE::Floor2Int #define CEIL SEACAVE::Ceil2Int #define CEIL2INT SEACAVE::Ceil2Int #define ROUND SEACAVE::Round2Int #define ROUND2INT SEACAVE::Round2Int #define SIN std::sin #define ASIN std::asin #define COS std::cos #define ACOS std::acos #define TAN std::tan #define ATAN std::atan #define ATAN2 std::atan2 #define POW std::pow #define POWI SEACAVE::powi #define LOG2I SEACAVE::log2i namespace SEACAVE { // F U N C T I O N S /////////////////////////////////////////////// template struct MakeIdentity { using type = T; }; template using MakeSigned = typename std::conditional::value,std::make_signed,SEACAVE::MakeIdentity>::type; template constexpr T1 Cast(const T2& v) { return static_cast(v); } template constexpr T& NEGATE(T& a) { return (a = -a); } template constexpr T SQUARE(const T& a) { return a * a; } template constexpr T CUBE(const T& a) { return a * a * a; } template inline T SQRT(const T& a) { return T(sqrt(a)); } template inline T EXP(const T& a) { return T(exp(a)); } template inline T LOGN(const T& a) { return T(log(a)); } template inline T LOG10(const T& a) { return T(log10(a)); } template constexpr T powi(T base, unsigned exp) { T result(1); while (exp) { if (exp & 1) result *= base; exp >>= 1; base *= base; } return result; } constexpr int log2i(unsigned val) { int ret = -1; while (val) { val >>= 1; ++ret; } return ret; } template constexpr inline int log2i() { return 1+log2i<(N>>1)>(); } template <> constexpr inline int log2i<0>() { return -1; } template <> constexpr inline int log2i<1>() { return 0; } template <> constexpr inline int log2i<2>() { return 1; } template inline T arithmeticSeries(T n, T a1=1, T d=1) { return (n*(a1*2+(n-1)*d))/2; } template constexpr T factorial(T n) { T ret = 1; while (n > 1) ret *= n--; return ret; } template constexpr T combinations(const T& n, const T& k) { ASSERT(n >= k); #if 1 T num = n; const T den = factorial(k); for (T i=n-k+1; i inline float FPOW2(float p) { if (bSafe && p < -126.f) { return 0.f; } else { ASSERT(p >= -126.f); CastF2I v; v.i = static_cast((1 << 23) * (p + 126.94269504f)); return v.f; } } template inline float FEXP(float v) { return FPOW2(1.44269504f * v); } // Inverse of the square root // Compute a fast 1 / sqrtf(v) approximation inline float RSQRT(float v) { #ifdef _FAST_INVSQRT // This code supposedly originates from Id-software const float halfV = v * 0.5f; (int32_t&)v = 0x5f3759df - (((int32_t&)v) >> 1); // Iterations of the Newton's method v = v * (1.5f - halfV * v * v); v = v * (1.5f - halfV * v * v); return v * (1.5f - halfV * v * v); #else return 1.f / SQRT(v); #endif } inline double RSQRT(const double& x) { #ifdef _FAST_INVSQRT double v = x; const double halfV = v * 0.5; (int64_t&)v = 0x5fe6ec85e7de30daLL - (((int64_t&)v) >> 1); // Iterations of the Newton's method v = v * (1.5 - halfV * v * v); v = v * (1.5 - halfV * v * v); v = v * (1.5 - halfV * v * v); return v * (1.5 - halfV * v * v); #else return 1.0 / SQRT(x); #endif } // approximate tanh template inline T TANH(const T& x) { const T x2 = x*x; #if 0 // Taylor series expansion (very inaccurate) return x*(1.0 + x2*(-T(1)/T(3) + x2*(T(2)/T(15) + x2*(-T(17)/T(315) + x2*(T(62)/T(2835) - x2*(T(1382)/T(155925))))))); #else // Lambert's continued fraction const T den = (((x2+T(378))*x2+T(17325))*x2+T(135135))*x; const T div = ((x2*T(28)+T(3150))*x2+T(62370))*x2+T(135135); return den/div; #endif } /*----------------------------------------------------------------*/ // Cubic root functions // cube root approximation using bit hack for 32-bit float (5 decimals) // (exploits the properties of IEEE 754 floating point numbers // by leveraging the fact that their binary representation is close to a log2 representation) inline float cbrt5(float x) { #if 0 CastF2I c(x); c.i = ((c.i-(127<<23))/3+(127<<23)); #else TAliasCast c(x); c.i = c.i/3 + 709921077u; #endif return c.f; } // cube root approximation using bit hack for 64-bit float // adapted from Kahan's cbrt (5 decimals) inline double cbrt5(double x) { TAliasCast c(0.0), d(x); c.i[1] = d.i[1]/3 + 715094163u; return c.f; } // iterative cube root approximation using Halley's method // faster convergence than Newton's method: (R/(a*a)+a*2)/3 template FORCEINLINE T cbrt_halley(const T& a, const T& R) { const T a3 = a*a*a; const T a3R = a3+R; return a * (a3R + R) / (a3 + a3R); } // fast cubic root (variable precision) template FORCEINLINE T fast_cbrt(const T& x) { return cbrt_halley(fast_cbrt(x), x); } template<> FORCEINLINE double fast_cbrt(const double& x) { return cbrt_halley((double)cbrt5((float)x), x); } template<> FORCEINLINE float fast_cbrt(const float& x) { return cbrt_halley(cbrt5(x), x); } // default cubic root function FORCEINLINE float CBRT(float x) { #ifdef _FAST_CBRT return fast_cbrt(x); #else return POW(x, 1.0f/3.0f); #endif } FORCEINLINE double CBRT(const double& x) { #ifdef _FAST_CBRT return fast_cbrt(x); #else return POW(x, 1.0/3.0); #endif } /*----------------------------------------------------------------*/ #if defined(__GNUC__) FORCEINLINE int PopCnt(uint32_t bb) { return __builtin_popcount(bb); } FORCEINLINE int PopCnt(uint64_t bb) { return __builtin_popcountll(bb); } FORCEINLINE int PopCnt15(uint64_t bb) { return __builtin_popcountll(bb); } FORCEINLINE int PopCntSparse(uint64_t bb) { return __builtin_popcountll(bb); } #elif defined(_USE_SSE) && defined(_M_AMD64) // 64 bit windows FORCEINLINE int PopCnt(uint32_t bb) { return (int)_mm_popcnt_u32(bb); } FORCEINLINE int PopCnt(uint64_t bb) { return (int)_mm_popcnt_u64(bb); } FORCEINLINE int PopCnt15(uint64_t bb) { return (int)_mm_popcnt_u64(bb); } FORCEINLINE int PopCntSparse(uint64_t bb) { return (int)_mm_popcnt_u64(bb); } #else // general purpose population count template constexpr int PopCnt(T bb) { STATIC_ASSERT(std::is_integral::value && std::is_unsigned::value); return std::bitset(bb).count(); } template<> inline int PopCnt(uint64_t bb) { const uint64_t k1 = (uint64_t)0x5555555555555555; const uint64_t k2 = (uint64_t)0x3333333333333333; const uint64_t k3 = (uint64_t)0x0F0F0F0F0F0F0F0F; const uint64_t k4 = (uint64_t)0x0101010101010101; bb -= (bb >> 1) & k1; bb = (bb & k2) + ((bb >> 2) & k2); bb = (bb + (bb >> 4)) & k3; return (bb * k4) >> 56; } // faster version assuming not more than 15 bits set, used in mobility // eval, posted on CCC forum by Marco Costalba of Stockfish team inline int PopCnt15(uint64_t bb) { unsigned w = unsigned(bb >> 32), v = unsigned(bb); v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits w -= (w >> 1) & 0x55555555; v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits w = ((w >> 2) & 0x33333333) + (w & 0x33333333); v += w; // 0-8 in 4 bits v *= 0x11111111; return int(v >> 28); } // version faster on sparsely populated bitboards inline int PopCntSparse(uint64_t bb) { int count = 0; while (bb) { count++; bb &= bb - 1; } return count; } #endif /*----------------------------------------------------------------*/ #ifdef _FAST_FLOAT2INT // fast float to int conversion // (xs routines at stereopsis: http://www.stereopsis.com/sree/fpu2006.html by Sree Kotay) const double _float2int_doublemagic = 6755399441055744.0; //2^52 * 1.5, uses limited precision to floor const double _float2int_doublemagicdelta = (1.5e-8); const double _float2int_doublemagicroundeps = (.5f-_float2int_doublemagicdelta); //almost .5f = .5f - 1e^(number of exp bit) FORCEINLINE int CRound2Int(const double& x) { const CastD2I c(x + _float2int_doublemagic); ASSERT(int32_t(floor(x+.5)) == c.i); return c.i; } #endif template FORCEINLINE INTTYPE Floor2Int(float x) { #ifdef _FAST_FLOAT2INT return CRound2Int(double(x)-_float2int_doublemagicroundeps); #else return static_cast(floor(x)); #endif } template FORCEINLINE INTTYPE Floor2Int(double x) { #ifdef _FAST_FLOAT2INT return CRound2Int(x-_float2int_doublemagicroundeps); #else return static_cast(floor(x)); #endif } template FORCEINLINE INTTYPE Ceil2Int(float x) { #ifdef _FAST_FLOAT2INT return CRound2Int(double(x)+_float2int_doublemagicroundeps); #else return static_cast(ceil(x)); #endif } template FORCEINLINE INTTYPE Ceil2Int(double x) { #ifdef _FAST_FLOAT2INT return CRound2Int(x+_float2int_doublemagicroundeps); #else return static_cast(ceil(x)); #endif } template FORCEINLINE INTTYPE Round2Int(float x) { #ifdef _FAST_FLOAT2INT return CRound2Int(double(x)+_float2int_doublemagicdelta); #else return static_cast(floor(x+.5f)); #endif } template FORCEINLINE INTTYPE Round2Int(double x) { #ifdef _FAST_FLOAT2INT return CRound2Int(x+_float2int_doublemagicdelta); #else return static_cast(floor(x+.5)); #endif } /*----------------------------------------------------------------*/ // INTERPOLATION // Linear interpolation inline float lerp(float u, float v, float x) { return u + (v - u) * x; } template inline Type lerp(const Type& u, const Type& v, float x) { return u + (v - u) * x; } // Cubic interpolation inline float cerp(float u0, float u1, float u2, float u3, float x) { const float p((u3 - u2) - (u0 - u1)); const float q((u0 - u1) - p); const float r(u2 - u0); return x * (x * (x * p + q) + r) + u1; } template inline Type cerp(const Type& u0, const Type& u1, const Type& u2, const Type& u3, float x) { const Type p((u3 - u2) - (u0 - u1)); const Type q((u0 - u1) - p); const Type r(u2 - u0); return x * (x * (x * p + q) + r) + u1; } /*----------------------------------------------------------------*/ // S T R U C T S /////////////////////////////////////////////////// #ifdef _USE_SSE // define utile functions to deal with SSE operations struct ALIGN(16) sse_vec4f { union { float v[4]; struct { float x; float y; float z; float w; }; }; inline sse_vec4f() {} inline sse_vec4f(const float* p) : x(p[0]), y(p[1]), z(p[2]), w(p[3]) {} inline sse_vec4f(float f0, float f1, float f2, float f3) : x(f0), y(f1), z(f2), w(f3) {} inline operator const float*() const {return v;} inline operator float*() {return v;} }; struct ALIGN(16) sse_vec2d { union { double v[2]; struct { double x; double y; }; }; inline sse_vec2d() {} inline sse_vec2d(const double* p) : x(p[0]), y(p[1]) {} inline sse_vec2d(const double& f0, const double& f1) : x(f0), y(f1) {} inline operator const double*() const {return v;} inline operator double*() {return v;} }; struct sse_f_t { typedef __m128 sse_t; typedef const sse_t& arg_sse_t; typedef float real_t; inline sse_f_t() {} inline sse_f_t(const sse_t& p) : v(p) {} inline sse_f_t(real_t p) : v(load1(p)) {} inline sse_f_t(const real_t* p) : v(load(p)) {} inline sse_f_t(real_t f0, real_t f1, real_t f2, real_t f3) : v(set(f0,f1,f2,f3)) {} inline operator sse_t() const {return v;} inline operator sse_t&() {return v;} inline sse_t operator ==(sse_t s) const {return cmpeq(v,s);} inline sse_t operator =(sse_t s) {return v=s;} inline sse_t operator +(sse_t s) const {return add(v,s);} inline sse_t operator +=(sse_t s) {return v=add(v,s);} inline sse_t operator -(sse_t s) const {return sub(v,s);} inline sse_t operator -=(sse_t s) {return v=sub(v,s);} inline sse_t operator *(sse_t s) const {return mul(v,s);} inline sse_t operator *=(sse_t s) {return v=mul(v,s);} inline sse_t operator /(sse_t s) const {return div(v,s);} inline sse_t operator /=(sse_t s) {return v=div(v,s);} inline void get(real_t* p) const {store(p,v);} static inline sse_t zero() {return _mm_setzero_ps();} static inline sse_t load1(real_t p) {return _mm_load1_ps(&p);} static inline sse_t load(const real_t* p) {return _mm_load_ps(p);} static inline sse_t loadu(const real_t* p) {return _mm_loadu_ps(p);} static inline sse_t set(real_t f0, real_t f1, real_t f2, real_t f3) {return _mm_set_ps(f0,f1,f2,f3);} static inline void store(real_t *p, sse_t s){_mm_store_ps(p,s);} static inline void storeu(real_t *p, sse_t s){_mm_storeu_ps(p,s);} static inline sse_t add(sse_t s1, sse_t s2) {return _mm_add_ps(s1,s2);} static inline sse_t sub(sse_t s1, sse_t s2) {return _mm_sub_ps(s1,s2);} static inline sse_t mul(sse_t s1, sse_t s2) {return _mm_mul_ps(s1,s2);} static inline sse_t div(sse_t s1, sse_t s2) {return _mm_div_ps(s1,s2);} static inline sse_t min(sse_t s1, sse_t s2) {return _mm_min_ps(s1,s2);} static inline sse_t max(sse_t s1, sse_t s2) {return _mm_max_ps(s1,s2);} static inline sse_t cmpeq(sse_t s1, sse_t s2){return _mm_cmpeq_ps(s1,s2);} static inline sse_t sqrt(sse_t s) {return _mm_sqrt_ps(s);} static inline sse_t rsqrt(sse_t s) {return _mm_rsqrt_ps(s);} static inline int floor2int(real_t f) {return _mm_cvtt_ss2si(_mm_load_ss(&f));} #ifdef _WIN32 static inline real_t sum(sse_t s) {return (s.m128_f32[0]+s.m128_f32[2])+(s.m128_f32[1]+s.m128_f32[3]);} static inline real_t sum3(sse_t s) {return (s.m128_f32[0]+s.m128_f32[2])+s.m128_f32[1];} #else static inline real_t sum(sse_t s) {real_t *f = (real_t*)(&s); return (f[0]+f[2])+(f[1]+f[3]);} static inline real_t sum3(sse_t s) {real_t *f = (real_t*)(&s); return (f[0]+f[2])+f[1];} #endif /* static inline real_t dot(sse_t s1, sse_t s2) { sse_t temp = _mm_dp_ps(s1, s2, 0xF1); real_t* f = (real_t*)(&temp); return f[0]; } */ static real_t dot(const real_t* a, const real_t* b, size_t size) { const real_t* const end = a+size; const size_t iters = (size>>2); real_t fres = 0.f; if (iters) { const real_t* const e = a+(iters<<2); sse_t mres = zero(); do { mres = _mm_add_ps(mres, _mm_mul_ps(_mm_loadu_ps(a), _mm_loadu_ps(b))); a += 4; b += 4; } while (a < e); fres = sum(mres); } while (a>1); real_t fres = 0.0; if (iters) { const real_t* const e = a+(iters<<1); sse_t mres = zero(); do { mres = _mm_add_pd(mres, _mm_mul_pd(_mm_loadu_pd(a), _mm_loadu_pd(b))); a += 2; b += 2; } while (a < e); fres = sum(mres); } while (a inline bool ISFINITE(const _Tp* x, size_t n) { for (size_t i=0; i inline bool ISINSIDE(_Tp v,_Tp l0,_Tp l1) { ASSERT(l0 inline bool ISINSIDES(_Tp v,_Tp l0,_Tp l1) { return l0 < l1 ? ISINSIDE(v, l0, l1) : ISINSIDE(v, l1, l0); } template inline _Tp CLAMP(_Tp v, _Tp l0, _Tp l1) { ASSERT(l0<=l1); return MINF(MAXF(v, l0), l1); } template inline _Tp CLAMPS(_Tp v, _Tp l0, _Tp l1) { return l0 <= l1 ? CLAMP(v, l0, l1) : CLAMP(v, l1, l0); } template inline _Tp SIGN(_Tp x) { if (x > _Tp(0)) return _Tp(1); if (x < _Tp(0)) return _Tp(-1); return _Tp(0); } template inline _Tp ABS(_Tp x) { return std::abs(x); } template constexpr _Tp ZEROTOLERANCE() { return _Tp(0); } template<> constexpr float ZEROTOLERANCE() { return FZERO_TOLERANCE; } template<> constexpr double ZEROTOLERANCE() { return ZERO_TOLERANCE; } template constexpr _Tp EPSILONTOLERANCE() { return std::numeric_limits<_Tp>::epsilon(); } template<> constexpr float EPSILONTOLERANCE() { return 0.00001f; } template<> constexpr double EPSILONTOLERANCE() { return 1e-10; } inline bool ISZERO(float x) { return ABS(x) < FZERO_TOLERANCE; } inline bool ISZERO(double x) { return ABS(x) < ZERO_TOLERANCE; } inline bool ISEQUAL(float x, float v) { return ABS(x-v) < FZERO_TOLERANCE; } inline bool ISEQUAL(double x, double v) { return ABS(x-v) < ZERO_TOLERANCE; } inline float INVZERO(float) { return FINV_ZERO; } inline double INVZERO(double) { return INV_ZERO; } template inline _Tp INVZERO(_Tp) { return std::numeric_limits<_Tp>::max(); } template inline _Tp INVERT(_Tp x) { return (x==_Tp(0) ? INVZERO(x) : _Tp(1)/x); } template inline _Tp SAFEDIVIDE(_Tp x, _Tp y) { return (y==_Tp(0) ? INVZERO(y) : x/y); } /*----------------------------------------------------------------*/ } // namespace SEACAVE #include "Random.h" #include "HalfFloat.h" namespace SEACAVE { // P R O T O T Y P E S ///////////////////////////////////////////// template class TMatrix; template class TAABB; template class TRay; template class TPlane; // 2D point struct template class TPoint2 : public cv::Point_ { public: typedef TYPE Type; typedef cv::Point_ Base; typedef cv::Size Size; typedef cv::Vec cvVec; typedef cv::Matx Vec; typedef cv::Matx VecT; #ifdef _USE_EIGEN EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(TYPE,2) typedef Eigen::Matrix EVec; typedef Eigen::Map CEVecMap; typedef Eigen::Map EVecMap; #endif using Base::x; using Base::y; static const TPoint2 ZERO; static const TPoint2 INF; public: inline TPoint2() {} inline TPoint2(const Size& rhs) : Base(rhs) {} template inline TPoint2(const cv::Point_& rhs) : Base((Type)rhs.x,(Type)rhs.y) {} template inline TPoint2(const cv::Matx& rhs) : Base(rhs(0),rhs(1)) {} template inline TPoint2(const cv::Matx& rhs) : Base(rhs(0),rhs(1)) {} #ifdef _USE_EIGEN inline TPoint2(const EVec& rhs) { operator EVecMap () = rhs; } #endif explicit inline TPoint2(const TYPE& _x) : Base(_x,_x) {} inline TPoint2(const TYPE& _x, const TYPE& _y) : Base(_x,_y) {} explicit inline TPoint2(const cv::Point3_& pt) : Base(pt.x/pt.z,pt.y/pt.z) {} template inline TPoint2& operator = (const cv::Point_& rhs) { Base::operator = (rhs); return *this; } template inline TPoint2& operator = (const cv::Matx& rhs) { operator Vec& () = rhs; return *this; } template inline TPoint2& operator = (const cv::Matx& rhs) { operator VecT& () = rhs; return *this; } #ifdef _USE_EIGEN inline TPoint2& operator = (const EVec& rhs) { operator EVecMap () = rhs; return *this; } #endif // conversion to another data type template inline operator TPoint2 () const { return TPoint2((T)x,(T)y); } // pointer to the first element access inline const TYPE* ptr() const { return &x; } inline TYPE* ptr() { return &x; } // 1D element access inline const TYPE& operator [](size_t i) const { ASSERT(i>=0 && i<2); return ptr()[i]; } inline TYPE& operator [](size_t i) { ASSERT(i>=0 && i<2); return ptr()[i]; } // Access point as Size equivalent inline operator const Size& () const { return *((const Size*)this); } inline operator Size& () { return *((Size*)this); } // Access point as vector equivalent inline operator const Vec& () const { return *((const Vec*)this); } inline operator Vec& () { return *((Vec*)this); } // Access point as transposed vector equivalent inline operator const VecT& () const { return *((const VecT*)this); } inline operator VecT& () { return *((VecT*)this); } #ifdef _USE_EIGEN // Access point as Eigen equivalent inline operator EVec () const { return CEVecMap((const TYPE*)this); } // Access point as Eigen::Map equivalent inline operator const CEVecMap () const { return CEVecMap((const TYPE*)this); } inline operator EVecMap () { return EVecMap((TYPE*)this); } #endif #ifdef _USE_BOOST // serialize template void serialize(Archive& ar, const unsigned int /*version*/) { ar & boost::serialization::base_object(*this); } #endif }; template const TPoint2 TPoint2::ZERO(0,0); template const TPoint2 TPoint2::INF(std::numeric_limits::infinity(),std::numeric_limits::infinity()); /*----------------------------------------------------------------*/ typedef TPoint2 Point2i; typedef TPoint2 Point2hf; typedef TPoint2 Point2f; typedef TPoint2 Point2d; /*----------------------------------------------------------------*/ // 3D point struct template class TPoint3 : public cv::Point3_ { public: typedef TYPE Type; typedef cv::Point3_ Base; typedef cv::Vec cvVec; typedef cv::Matx Vec; typedef cv::Matx VecT; #ifdef _USE_EIGEN EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(TYPE,3) typedef Eigen::Matrix EVec; typedef Eigen::Map CEVecMap; typedef Eigen::Map EVecMap; #endif using Base::x; using Base::y; using Base::z; static const TPoint3 ZERO; static const TPoint3 INF; public: inline TPoint3() {} template inline TPoint3(const cv::Point3_& rhs) : Base((Type)rhs.x,(Type)rhs.y,(Type)rhs.z) {} template inline TPoint3(const cv::Matx& rhs) : Base(rhs(0),rhs(1),rhs(2)) {} template inline TPoint3(const cv::Matx& rhs) : Base(rhs(0),rhs(1),rhs(2)) {} #ifdef _USE_EIGEN inline TPoint3(const EVec& rhs) { operator EVecMap () = rhs; } #endif explicit inline TPoint3(const TYPE& _x) : Base(_x,_x,_x) {} inline TPoint3(const TYPE& _x, const TYPE& _y, const TYPE& _z) : Base(_x,_y,_z) {} template inline TPoint3(const cv::Point_& pt, const T& _z=T(1)) : Base(pt.x,pt.y,_z) {} template inline TPoint3(const cv::Point_& pt, const T2& _z) : Base(pt.x,pt.y,_z) {} template inline TPoint3& operator = (const cv::Point3_& rhs) { Base::operator = (rhs); return *this; } template inline TPoint3& operator = (const cv::Matx& rhs) { operator Vec& () = rhs; return *this; } template inline TPoint3& operator = (const cv::Matx& rhs) { operator VecT& () = rhs; return *this; } #ifdef _USE_EIGEN inline TPoint3& operator = (const EVec& rhs) { operator EVecMap () = rhs; return *this; } #endif // conversion to another data type template inline operator TPoint3 () const { return TPoint3((T)x,(T)y,(T)z); } // pointer to the first element access inline const TYPE* ptr() const { return &x; } inline TYPE* ptr() { return &x; } // 1D element access inline const TYPE& operator [](BYTE i) const { ASSERT(i<3); return ptr()[i]; } inline TYPE& operator [](BYTE i) { ASSERT(i<3); return ptr()[i]; } // Access point as vector equivalent inline operator const Vec& () const { return *reinterpret_cast(this); } inline operator Vec& () { return *reinterpret_cast(this); } // Access point as transposed vector equivalent inline operator const VecT& () const { return *reinterpret_cast(this); } inline operator VecT& () { return *reinterpret_cast(this); } #ifdef _USE_EIGEN // Access point as Eigen equivalent inline operator EVec () const { return CEVecMap((const TYPE*)this); } // Access point as Eigen::Map equivalent inline operator const EVecMap () const { return CEVecMap((const TYPE*)this); } inline operator EVecMap () { return EVecMap((TYPE*)this); } #endif // rotate point using the given parametrized rotation (axis-angle) inline void RotateAngleAxis(const TPoint3& rot) { return (*this) = RotateAngleAxis((*this), rot); } static TPoint3 RotateAngleAxis(const TPoint3& X, const TPoint3& rot); #ifdef _USE_BOOST // serialize template void serialize(Archive& ar, const unsigned int /*version*/) { ar & boost::serialization::base_object(*this); } #endif }; template const TPoint3 TPoint3::ZERO(0,0,0); template const TPoint3 TPoint3::INF(std::numeric_limits::infinity(),std::numeric_limits::infinity(),std::numeric_limits::infinity()); /*----------------------------------------------------------------*/ typedef TPoint3 Point3i; typedef TPoint3 Point3hf; typedef TPoint3 Point3f; typedef TPoint3 Point3d; /*----------------------------------------------------------------*/ // matrix struct template class TMatrix : public cv::Matx { public: typedef TYPE Type; typedef cv::Matx Base; typedef cv::Vec Vec; #ifdef _USE_EIGEN EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(TYPE,m*n) typedef Eigen::Matrix1?Eigen::RowMajor:Eigen::Default)> EMat; typedef Eigen::Map CEMatMap; typedef Eigen::Map EMatMap; #endif using Base::val; using Base::channels; enum { elems = m*n }; static const TMatrix ZERO; static const TMatrix IDENTITY; static const TMatrix INF; public: inline TMatrix() {} template inline TMatrix(const cv::Matx& rhs) : Base(rhs) {} template inline TMatrix(const cv::Point_& rhs) : Base(rhs.x, rhs.y) {} template inline TMatrix(const cv::Point3_& rhs) : Base(rhs.x, rhs.y, rhs.z) {} inline TMatrix(const cv::Mat& rhs) : Base(rhs) {} #ifdef _USE_EIGEN inline TMatrix(const EMat& rhs) { operator EMatMap () = rhs; } #endif TMatrix(TYPE v0); //!< 1x1 matrix TMatrix(TYPE v0, TYPE v1); //!< 1x2 or 2x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2); //!< 1x3 or 3x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3); //!< 1x4, 2x2 or 4x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4); //!< 1x5 or 5x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4, TYPE v5); //!< 1x6, 2x3, 3x2 or 6x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4, TYPE v5, TYPE v6); //!< 1x7 or 7x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4, TYPE v5, TYPE v6, TYPE v7); //!< 1x8, 2x4, 4x2 or 8x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4, TYPE v5, TYPE v6, TYPE v7, TYPE v8); //!< 1x9, 3x3 or 9x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4, TYPE v5, TYPE v6, TYPE v7, TYPE v8, TYPE v9); //!< 1x10, 2x5 or 5x2 or 10x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4, TYPE v5, TYPE v6, TYPE v7, TYPE v8, TYPE v9, TYPE v10, TYPE v11); //!< 1x12, 2x6, 3x4, 4x3, 6x2 or 12x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4, TYPE v5, TYPE v6, TYPE v7, TYPE v8, TYPE v9, TYPE v10, TYPE v11, TYPE v12, TYPE v13); //!< 1x14, 2x7, 7x2 or 14x1 matrix TMatrix(TYPE v0, TYPE v1, TYPE v2, TYPE v3, TYPE v4, TYPE v5, TYPE v6, TYPE v7, TYPE v8, TYPE v9, TYPE v10, TYPE v11, TYPE v12, TYPE v13, TYPE v14, TYPE v15); //!< 1x16, 4x4 or 16x1 matrix explicit TMatrix(const TYPE* vals); //!< initialize from a plain array TMatrix(const TMatrix& a, const TMatrix& b, cv::Matx_AddOp) : Base(a, b, cv::Matx_AddOp()) {} TMatrix(const TMatrix& a, const TMatrix& b, cv::Matx_SubOp) : Base(a, b, cv::Matx_SubOp()) {} template TMatrix(const TMatrix& a, TYPE2 alpha, cv::Matx_ScaleOp) : Base(a, alpha, cv::Matx_ScaleOp()) {} TMatrix(const TMatrix& a, const TMatrix& b, cv::Matx_MulOp) : Base(a, b, cv::Matx_MulOp()) {} TMatrix(const TMatrix& a, const TMatrix& b, cv::Matx_DivOp) : Base(a, b, cv::Matx_DivOp()) {} template TMatrix(const TMatrix& a, const TMatrix& b, cv::Matx_MatMulOp) : Base(a, b, cv::Matx_MatMulOp()) {} TMatrix(const TMatrix& a, cv::Matx_TOp) : Base(a, cv::Matx_TOp()) {} template inline TMatrix& operator = (const cv::Matx& rhs) { Base::operator = (rhs); return *this; } inline TMatrix& operator = (const cv::Mat& rhs) { Base::operator = (rhs); return *this; } #ifdef _USE_EIGEN inline TMatrix& operator = (const EMat& rhs) { operator EMatMap () = rhs; return *this; } #endif inline bool IsEqual(const Base&) const; inline bool IsEqual(const Base&, TYPE eps) const; // 1D element access inline const TYPE& operator [](size_t i) const { ASSERT(i(this); } inline operator Vec& () { return *reinterpret_cast(this); } #ifdef _USE_EIGEN // Access point as Eigen equivalent inline operator EMat () const { return CEMatMap((const TYPE*)val); } // Access point as Eigen::Map equivalent inline operator CEMatMap() const { return CEMatMap((const TYPE*)val); } inline operator EMatMap () { return EMatMap((TYPE*)val); } #endif // calculate right null-space of this matrix ([n,n-m]) inline TMatrix RightNullSpace(int flags = 0) const; // calculate right/left null-vector of this matrix ([n/m,1]) inline TMatrix RightNullVector(int flags = 0) const; inline TMatrix LeftNullVector(int flags = 0) const; #ifdef _USE_BOOST // serialize template void serialize(Archive& ar, const unsigned int /*version*/) { ar & boost::serialization::base_object(*this); } #endif }; template const TMatrix TMatrix::ZERO(TMatrix::zeros()); template const TMatrix TMatrix::IDENTITY(TMatrix::eye()); template const TMatrix TMatrix::INF(TMatrix::all(std::numeric_limits::infinity())); /*----------------------------------------------------------------*/ // generic matrix struct template class TDMatrix : public cv::Mat_ { public: typedef TYPE Type; typedef cv::Mat_ Base; typedef cv::Size Size; #ifdef _USE_EIGEN typedef Eigen::Matrix EMat; typedef Eigen::Map CEMatMap; typedef Eigen::Map EMatMap; #endif using Base::rows; using Base::cols; using Base::data; using Base::step; using Base::dims; public: inline TDMatrix() {} inline TDMatrix(const Base& rhs) : Base(rhs) {} inline TDMatrix(const cv::Mat& rhs) : Base(rhs) {} inline TDMatrix(const cv::MatExpr& rhs) : Base(rhs) {} inline TDMatrix(int _rows, int _cols) : Base(_rows, _cols) {} inline TDMatrix(int _rows, int _cols, TYPE* _data, size_t _step=Base::AUTO_STEP) : Base(_rows, _cols, _data, _step) {} inline TDMatrix(const Size& sz) : Base(sz) {} inline TDMatrix(const Size& sz, const TYPE& v) : Base(sz, v) {} inline TDMatrix(const Size& sz, TYPE* _data, size_t _step=Base::AUTO_STEP) : Base(sz.height, sz.width, _data, _step) {} #ifdef _USE_EIGEN inline TDMatrix(const EMat& rhs) { operator EMatMap () = rhs; } #endif inline TDMatrix& operator = (const Base& rhs) { Base::operator=(rhs); return *this; } inline TDMatrix& operator = (const cv::MatExpr& rhs) { Base::operator=(rhs); return *this; } #ifdef _USE_EIGEN inline TDMatrix& operator = (const EMat& rhs) { operator EMatMap () = rhs; return *this; } #endif /// Construct the 2D matrix with the desired size and init its elements inline void construct(int _rows, int _cols) { Base::create(_rows, _cols); for (int i=0; i(i,j)) TYPE; } inline void construct(const Size& sz) { construct(sz.height, sz.width); } inline void destroy() { for (int i=0; i(i,j)->~TYPE(); } /// Set all elements to the given value inline void memset(uint8_t v) { ASSERT(dims == 2 && cv::Mat::isContinuous()); ::memset(data, v, row_stride()*rows); } inline void fill(const TYPE& v) { ASSERT(dims == 2); for (int i=0; i(i,j) = v; } /// What is the row stride of the matrix? inline size_t row_stride() const { ASSERT(dims == 2); return step[0]; } /// What is the elem stride of the matrix? inline size_t elem_stride() const { ASSERT(dims == 2 && step[1] == sizeof(TYPE)); return step[1]; } /// Compute the area of the 2D matrix inline int area() const { ASSERT(dims == 2); return cols*rows; } /// Is this coordinate inside the 2D matrix? template static inline typename std::enable_if::value,bool>::type isInside(const cv::Point_& pt, const cv::Size& size) { return pt.x>=T(0) && pt.y>=T(0) && pt.x static inline typename std::enable_if::value,bool>::type isInside(const cv::Point_& pt, const cv::Size& size) { return pt.x>=T(0) && pt.y>=T(0) && pt.x<=T(size.width) && pt.y<=T(size.height); } template inline bool isInside(const cv::Point_& pt) const { return isInside(pt, Base::size()); } /// Is this coordinate inside the 2D matrix, and not too close to the edges? /// @param border: the size of the border inline bool isInsideWithBorder(const Size& pt, int border) const { return pt.width>=border && pt.height>=border && pt.width inline typename std::enable_if::value,bool>::type isInsideWithBorder(const cv::Point_& pt, int border) const { return pt.x>=border && pt.y>=border && pt.x inline typename std::enable_if::value,bool>::type isInsideWithBorder(const cv::Point_& pt, int border) const { return pt.x>=T(border) && pt.y>=T(border) && pt.x<=T(Base::size().width-(border+1)) && pt.y<=T(Base::size().height-(border+1)); } template inline typename std::enable_if::value,bool>::type isInsideWithBorder(const cv::Point_& pt) const { return pt.x>=border && pt.y>=border && pt.x inline typename std::enable_if::value,bool>::type isInsideWithBorder(const cv::Point_& pt) const { return pt.x>=T(border) && pt.y>=T(border) && pt.x<=T(Base::size().width-(border+1)) && pt.y<=T(Base::size().height-(border+1)); } template static inline void clip(TPoint2& ptMin, TPoint2& ptMax, const cv::Size& size) { if (ptMin.x < T(border)) ptMin.x = T(border); if (ptMin.y < T(border)) ptMin.y = T(border); if (ptMax.x >= T(size.width-border)) ptMax.x = T(size.width-(border+1)); if (ptMax.y >= T(size.height-border)) ptMax.y = T(size.height-(border+1)); } template inline void clip(TPoint2& ptMin, TPoint2& ptMax) const { clip(ptMin, ptMax, Base::size()); } /// Remove the given element from the vector inline void remove(int idx) { // replace the removed element by the last one and decrease the size ASSERT(rows == 1 || cols == 1); const int last = area()-1; Base::operator()(idx) = Base::operator()(last); Base::resize((size_t)last); } /** @author koeser @warning very slow, generic implementation (order "n!"), better to use matrix decomposition (see BIAS/MathAlgo/Lapack.hh) */ inline TYPE getDetSquare() const; /** @brief computes the adjoint matrix @author Christian Beder */ inline TDMatrix getAdjoint() const; /** @brief compute square system matrix dest = A^T * A @param dest holds result of Transpose * this If you want to solve A * x = b, where A has more rows than columns, a common technique is to solve x = (A^T * A)^-1 * A^T * b. This function provides a fast way to compute A^T*A from A. @author grest/koeser */ inline void getSystemMatrix(TDMatrix& dest) const; /** @brief componentwise: this = 0.5(this + this^T) yields symmetric matrix only allowed for square shaped matrices @author koeser 01/2007 */ inline void makeSymmetric(); /** Return the L1 norm: |a| + |b| + |c| + ... @author Ingo Thomsen @date 04/11/2002 @status untested **/ inline TYPE getNormL1() const; /** Return the L2 norm: a^2 + b^2 + c^2 + ... @author woelk 07/2004 */ inline double getNormL2() const; /** Kronecker-product with matrix, result in dest */ void Kronecker(const TDMatrix& B, TDMatrix& dest) const; /** @brief swaps two rows @author woelk 05/2008 www.vision-n.de */ void SwapRows(int i, int r); /** @brief use the Gauss Jordan Algorithm to transform the matrix to reduced row echelon form. @author woelk 05/2008 www.vision-n.de */ void GaussJordan(); //! more convenient forms of row and element access operators const TYPE& operator [](size_t i) const { return cv::Mat::at((int)i); } TYPE& operator [](size_t i) { return cv::Mat::at((int)i); } /// Access an element from the matrix. Bounds checking is only performed in debug mode. inline const TYPE& operator [] (const Size& pos) const { ASSERT(isInside(pos) && elem_stride() == sizeof(TYPE)); return ((const TYPE*)data)[pos.height*row_stride() + pos.width]; } inline TYPE& operator [] (const Size& pos) { ASSERT(isInside(pos) && elem_stride() == sizeof(TYPE)); return ((TYPE*)data)[pos.height*row_stride() + pos.width]; } /// pointer to the beginning of the matrix data inline const TYPE* getData() const { ASSERT(cv::Mat::empty() || cv::Mat::isContinuous()); return (const TYPE*)data; } inline TYPE* getData() { ASSERT(cv::Mat::empty() || cv::Mat::isContinuous()); return (TYPE*)data; } #ifdef _USE_EIGEN // Access point as Eigen equivalent inline operator EMat () const { return CEMatMap(getData(), rows, cols); } // Access point as Eigen::Map equivalent inline operator const CEMatMap () const { return CEMatMap(getData(), rows, cols); } inline operator EMatMap () { return EMatMap(getData(), rows, cols); } #endif #ifdef _USE_BOOST // serialize template void serialize(Archive& ar, const unsigned int /*version*/) { ar & boost::serialization::base_object(*this); } #endif }; /*----------------------------------------------------------------*/ typedef TDMatrix DMatrix; typedef TDMatrix DMatrix8S; typedef TDMatrix DMatrix8U; typedef TDMatrix DMatrix32S; typedef TDMatrix DMatrix32U; typedef TDMatrix DMatrix32F; typedef TDMatrix DMatrix64F; typedef CLISTDEF2(DMatrix) DMatrixArr; typedef CLISTDEF2(cv::Mat) MatArr; /*----------------------------------------------------------------*/ // generic vector struct template class TDVector : public TDMatrix { public: typedef TYPE Type; typedef TDMatrix Base; typedef typename Base::Base BaseBase; typedef cv::Size Size; using Base::rows; using Base::cols; using Base::data; public: inline TDVector() {} inline TDVector(const Base& rhs) : Base(rhs) {} inline TDVector(const cv::Mat& rhs) : Base(rhs) {} inline TDVector(const cv::MatExpr& rhs) : Base(rhs) {} inline TDVector(int _rows) : Base(_rows, 1) {} inline TDVector(int _rows, const TYPE& v) : Base(Size(_rows,1), v) {} inline TDVector(int _rows, TYPE* _data, size_t _step=Base::AUTO_STEP) : Base(_rows, 1, _data, _step) {} inline TDVector& operator = (const Base& rhs) { BaseBase::operator=(rhs); return *this; } inline TDVector& operator = (const BaseBase& rhs) { BaseBase::operator=(rhs); return *this; } inline TDVector& operator = (const cv::MatExpr& rhs) { BaseBase::operator=(rhs); return *this; } //! equivalent to Mat::create(_rows, 1, DataType<_Tp>::type) inline void create(int _rows) { BaseBase::create(_rows, 1); } /** outer product, constructs a matrix. Often written as v * v^T for col vectors @author Daniel Grest, Oct 2002 @status tested */ TDMatrix getOuterProduct(const TDVector& v) const; /** kronecker product @author woelk 08/2004 */ void getKroneckerProduct(const TDVector& arg, TDVector& dst) const; }; /*----------------------------------------------------------------*/ typedef TDVector DVector; typedef TDVector DVector8S; typedef TDVector DVector8U; typedef TDVector DVector32S; typedef TDVector DVector32U; typedef TDVector DVector32F; typedef TDVector DVector64F; typedef CLISTDEF2(DVector) DVectorArr; /*----------------------------------------------------------------*/ // generic color type // Here the color order means the order the data is stored on this machine. // For example BGR means that the blue byte is stored first and the red byte last, // which correspond to the RGB format on a little-endian machine. #define _COLORMODE_BGR 1 // little-endian #define _COLORMODE_RGB 2 // big-endian #ifndef _COLORMODE #define _COLORMODE _COLORMODE_BGR #endif template class ColorType { public: typedef TYPE value_type; typedef value_type alt_type; static const value_type ONE; static const alt_type ALTONE; }; template<> class ColorType { public: typedef uint8_t value_type; typedef float alt_type; static const value_type ONE; static const alt_type ALTONE; }; template<> class ColorType { public: typedef uint32_t value_type; typedef float alt_type; static const value_type ONE; static const alt_type ALTONE; }; template<> class ColorType { public: typedef float value_type; typedef uint8_t alt_type; static const value_type ONE; static const alt_type ALTONE; }; template<> class ColorType { public: typedef double value_type; typedef uint8_t alt_type; static const value_type ONE; static const alt_type ALTONE; }; /*----------------------------------------------------------------*/ template struct TPixel { union { struct { #if _COLORMODE == _COLORMODE_BGR TYPE b; TYPE g; TYPE r; #endif #if _COLORMODE == _COLORMODE_RGB TYPE r; TYPE g; TYPE b; #endif }; struct { TYPE c0; TYPE c1; TYPE c2; }; TYPE c[3]; }; typedef typename ColorType::alt_type ALT; typedef TYPE Type; typedef TPoint3 Pnt; static const TPixel BLACK; static const TPixel WHITE; static const TPixel GRAY; static const TPixel RED; static const TPixel GREEN; static const TPixel BLUE; static const TPixel YELLOW; static const TPixel MAGENTA; static const TPixel CYAN; // init inline TPixel() {} template inline TPixel(const TPixel& p) #if _COLORMODE == _COLORMODE_BGR : b(TYPE(p.b)), g(TYPE(p.g)), r(TYPE(p.r)) {} #endif #if _COLORMODE == _COLORMODE_RGB : r(TYPE(p.r)), g(TYPE(p.g)), b(TYPE(p.b)) {} #endif inline TPixel(TYPE _r, TYPE _g, TYPE _b) #if _COLORMODE == _COLORMODE_BGR : b(_b), g(_g), r(_r) {} #endif #if _COLORMODE == _COLORMODE_RGB : r(_r), g(_g), b(_b) {} #endif inline TPixel(const Pnt& col) : c0(col.x), c1(col.y), c2(col.z) {} explicit inline TPixel(uint32_t col) #if _COLORMODE == _COLORMODE_BGR : b(TYPE(col&0xFF)), g(TYPE((col>>8)&0xFF)), r(TYPE((col>>16)&0xFF)) {} #endif #if _COLORMODE == _COLORMODE_RGB : r(TYPE((col>>16)&0xFF)), g(TYPE((col>>8)&0xFF)), b(TYPE(col&0xFF)) {} #endif // set/get from default type inline TPixel& set(TYPE _r, TYPE _g, TYPE _b) { r = _r; g = _g; b = _b; return *this; } inline TPixel& set(const TYPE* clr) { c[0] = clr[0]; c[1] = clr[1]; c[2] = clr[2]; return *this; } inline void get(TYPE& _r, TYPE& _g, TYPE& _b) const { _r = r; _g = g; _b = b; } inline void get(TYPE* clr) const { clr[0] = c[0]; clr[1] = c[1]; clr[2] = c[2]; } // set/get from alternative type inline TPixel& set(ALT _r, ALT _g, ALT _b) { r = TYPE(_r); g = TYPE(_g); b = TYPE(_b); return *this; } inline TPixel& set(const ALT* clr) { c[0] = TYPE(clr[0]); c[1] = TYPE(clr[1]); c[2] = TYPE(clr[2]); return *this; } inline void get(ALT& _r, ALT& _g, ALT& _b) const { _r = ALT(r); _g = ALT(g); _b = ALT(b); } inline void get(ALT* clr) const { clr[0] = ALT(c[0]); clr[1] = ALT(c[1]); clr[2] = ALT(c[2]); } template inline TPixel::value || !std::is_same::value,T>::type> cast() const { return TPixel(T(r), T(g), T(b)); } template inline TPixel::value && std::is_same::value,T>::type> cast() const { return TPixel( (uint8_t)CLAMP(ROUND2INT(r), 0, 255), (uint8_t)CLAMP(ROUND2INT(g), 0, 255), (uint8_t)CLAMP(ROUND2INT(b), 0, 255) ); } // set/get as vector inline const TYPE& operator[](size_t i) const { ASSERT(i<3); return c[i]; } inline TYPE& operator[](size_t i) { ASSERT(i<3); return c[i]; } // access as point equivalent template inline operator TPoint3() const { return TPoint3(T(c[0]), T(c[1]), T(c[2])); } // access as vector equivalent inline operator const Pnt& () const { return *((const Pnt*)this); } inline operator Pnt& () { return *((Pnt*)this); } // access as cv::Scalar equivalent inline operator cv::Scalar () const { return cv::Scalar(c[0], c[1], c[2], TYPE(0)); } // compare inline bool operator==(const TPixel& col) const { return (memcmp(c, col.c, sizeof(TPixel)) == 0); } inline bool operator!=(const TPixel& col) const { return (memcmp(c, col.c, sizeof(TPixel)) != 0); } // operators inline TPixel operator*(const TPixel& v) const { return TPixel(r*v.r, g*v.g, b*v.b); } template inline TPixel operator*(T v) const { return TPixel((TYPE)(v*r), (TYPE)(v*g), (TYPE)(v*b)); } template inline TPixel& operator*=(T v) { return (*this = operator*(v)); } inline TPixel operator/(const TPixel& v) const { return TPixel(r/v.r, g/v.g, b/v.b); } template inline TPixel operator/(T v) const { return operator*(T(1)/v); } template inline TPixel& operator/=(T v) { return (*this = operator/(v)); } inline TPixel operator+(const TPixel& v) const { return TPixel(r+v.r, g+v.g, b+v.b); } template inline TPixel operator+(T v) const { return TPixel((TYPE)(r+v), (TYPE)(g+v), (TYPE)(b+v)); } template inline TPixel& operator+=(T v) { return (*this = operator+(v)); } inline TPixel operator-(const TPixel& v) const { return TPixel(r-v.r, g-v.g, b-v.b); } template inline TPixel operator-(T v) const { return TPixel((TYPE)(r-v), (TYPE)(g-v), (TYPE)(b-v)); } template inline TPixel& operator-=(T v) { return (*this = operator-(v)); } inline uint32_t toDWORD() const { return RGBA((uint8_t)r, (uint8_t)g, (uint8_t)b, (uint8_t)0); } // tools template static TPixel colorRamp(VT v, VT vmin, VT vmax); static TPixel gray2color(ALT v); #ifdef _USE_BOOST // serialize template void serialize(Archive& ar, const unsigned int /*version*/) { ar & c; } #endif }; template <> inline TPixel& TPixel::set(uint8_t _r, uint8_t _g, uint8_t _b) { r = float(_r)/255; g = float(_g)/255; b = float(_b)/255; return *this; } template <> inline void TPixel::get(uint8_t& _r, uint8_t& _g, uint8_t& _b) const { _r = (uint8_t)CLAMP(ROUND2INT(r*255), 0, 255); _g = (uint8_t)CLAMP(ROUND2INT(g*255), 0, 255); _b = (uint8_t)CLAMP(ROUND2INT(b*255), 0, 255); } template <> inline TPixel& TPixel::set(float _r, float _g, float _b) { r = (uint8_t)CLAMP(ROUND2INT(_r*255), 0, 255); g = (uint8_t)CLAMP(ROUND2INT(_g*255), 0, 255); b = (uint8_t)CLAMP(ROUND2INT(_b*255), 0, 255); return *this; } template <> inline void TPixel::get(float& _r, float& _g, float& _b) const { _r = float(r)/255; _g = float(g)/255; _b = float(b)/255; } /*----------------------------------------------------------------*/ typedef TPixel Pixel8U; typedef TPixel Pixel32F; typedef TPixel Pixel64F; /*----------------------------------------------------------------*/ template struct TColor { union { struct { #if _COLORMODE == _COLORMODE_BGR TYPE b; TYPE g; TYPE r; TYPE a; #endif #if _COLORMODE == _COLORMODE_RGB TYPE a; TYPE r; TYPE g; TYPE b; #endif }; struct { TYPE c0; TYPE c1; TYPE c2; TYPE c3; }; TYPE c[4]; }; typedef typename ColorType::alt_type ALT; typedef TYPE Type; typedef TPixel Pxl; typedef TPoint3 Pnt; static const TColor BLACK; static const TColor WHITE; static const TColor GRAY; static const TColor RED; static const TColor GREEN; static const TColor BLUE; static const TColor YELLOW; static const TColor MAGENTA; static const TColor CYAN; // init inline TColor() {} template inline TColor(const TColor& p) : r(TYPE(p.r)), g(TYPE(p.g)), b(TYPE(p.b)), a(TYPE(p.a)) {} inline TColor(TYPE _r, TYPE _g, TYPE _b, TYPE _a=ColorType::ONE) : r(_r), g(_g), b(_b), a(_a) {} inline TColor(const Pxl& col, TYPE _a=ColorType::ONE) : r(col.r), g(col.g), b(col.b), a(_a) {} #if _COLORMODE == _COLORMODE_BGR inline TColor(const Pnt& col, TYPE _a=ColorType::ONE) : b(col.x), g(col.y), r(col.z), a(_a) {} #endif #if _COLORMODE == _COLORMODE_RGB inline TColor(const Pnt& col, TYPE _a=ColorType::ONE) : r(col.x), g(col.y), b(col.z), a(_a) {} #endif explicit inline TColor(uint32_t col) : r(TYPE((col>>16)&0xFF)), g(TYPE((col>>8)&0xFF)), b(TYPE(col&0xFF)), a(TYPE((col>>24)&0xFF)) {} // set/get from default type inline TColor& set(TYPE _r, TYPE _g, TYPE _b, TYPE _a=ColorType::ONE) { r = _r; g = _g; b = _b; a = _a; return *this; } inline TColor& set(const TYPE* clr) { c[0] = clr[0]; c[1] = clr[1]; c[2] = clr[2]; c[3] = clr[3]; return *this; } inline void get(TYPE& _r, TYPE& _g, TYPE& _b, TYPE& _a) const { _r = r; _g = g; _b = b; _a = a; } inline void get(TYPE* clr) const { clr[0] = c[0]; clr[1] = c[1]; clr[2] = c[2]; clr[3] = c[3]; } // set/get from alternative type inline TColor& set(ALT _r, ALT _g, ALT _b, ALT _a=ColorType::ALTONE) { r = TYPE(_r); g = TYPE(_g); b = TYPE(_b); a = TYPE(_a); return *this; } inline TColor& set(const ALT* clr) { c[0] = TYPE(clr[0]); c[1] = TYPE(clr[1]); c[2] = TYPE(clr[2]); c[3] = TYPE(clr[3]); return *this; } inline void get(ALT& _r, ALT& _g, ALT& _b, ALT& _a) const { _r = ALT(r); _g = ALT(g); _b = ALT(b); _a = ALT(a); } inline void get(ALT* clr) const { clr[0] = ALT(c[0]); clr[1] = ALT(c[1]); clr[2] = ALT(c[2]); clr[3] = ALT(c[3]); } template inline TColor::value || !std::is_same::value,T>::type> cast() const { return TColor(T(r), T(g), T(b), T(a)); } template inline TColor::value && std::is_same::value,T>::type> cast() const { return TColor( (uint8_t)CLAMP(ROUND2INT(r), 0, 255), (uint8_t)CLAMP(ROUND2INT(g), 0, 255), (uint8_t)CLAMP(ROUND2INT(b), 0, 255), (uint8_t)CLAMP(ROUND2INT(a), 0, 255) ); } // set/get as vector inline const TYPE& operator[](size_t i) const { ASSERT(i<4); return c[i]; } inline TYPE& operator[](size_t i) { ASSERT(i<4); return c[i]; } // access as pixel equivalent inline operator const Pxl& () const { return *((const Pxl*)this); } inline operator Pxl& () { return *((Pxl*)this); } // access as point equivalent inline operator const Pnt& () const { return *((const Pnt*)this); } inline operator Pnt& () { return *((Pnt*)this); } // access as cv::Scalar equivalent inline operator cv::Scalar () const { return cv::Scalar(c[0], c[1], c[2], c[3]); } // compare inline bool operator==(const TColor& col) const { return (memcmp(c, col.c, sizeof(TColor)) == 0); } inline bool operator!=(const TColor& col) const { return (memcmp(c, col.c, sizeof(TColor)) != 0); } // operators inline TColor operator*(const TColor& v) const { return TColor(r*v.r, g*v.g, b*v.b, a*v.a); } template inline TColor operator*(T v) const { return TColor((TYPE)(v*r), (TYPE)(v*g), (TYPE)(v*b), (TYPE)(v*a)); } template inline TColor& operator*=(T v) { return (*this = operator*(v)); } inline TColor operator/(const TColor& v) const { return TColor(r/v.r, g/v.g, b/v.b, a/v.a); } template inline TColor operator/(T v) const { return operator*(T(1)/v); } template inline TColor& operator/=(T v) { return (*this = operator/(v)); } inline TColor operator+(const TColor& v) const { return TColor(r+v.r, g+v.g, b+v.b, a+v.a); } template inline TColor operator+(T v) const { return TColor((TYPE)(r+v), (TYPE)(g+v), (TYPE)(b+v), (TYPE)(a+v)); } template inline TColor& operator+=(T v) { return (*this = operator+(v)); } inline TColor operator-(const TColor& v) const { return TColor(r-v.r, g-v.g, b-v.b, a-v.a); } template inline TColor operator-(T v) const { return TColor((TYPE)(r-v), (TYPE)(g-v), (TYPE)(b-v), (TYPE)(a-v)); } template inline TColor& operator-=(T v) { return (*this = operator-(v)); } inline uint32_t toDWORD() const { return RGBA((uint8_t)r, (uint8_t)g, (uint8_t)b, (uint8_t)a); } #ifdef _USE_BOOST // serialize template void serialize(Archive& ar, const unsigned int /*version*/) { ar & c; } #endif }; template <> inline TColor& TColor::set(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) { r = float(_r)/255; g = float(_g)/255; b = float(_b)/255; a = float(_a)/255; return *this; } template <> inline void TColor::get(uint8_t& _r, uint8_t& _g, uint8_t& _b, uint8_t& _a) const { _r = uint8_t(r*255); _g = uint8_t(g*255); _b = uint8_t(b*255); _a = uint8_t(a*255); } template <> inline TColor& TColor::set(float _r, float _g, float _b, float _a) { r = uint8_t(_r*255); g = uint8_t(_g*255); b = uint8_t(_b*255); a = uint8_t(_a*255); return *this; } template <> inline void TColor::get(float& _r, float& _g, float& _b, float& _a) const { _r = float(r)/255; _g = float(g)/255; _b = float(b)/255; _a = float(a)/255; } template <> inline bool TColor::operator==(const TColor& col) const { return (*((const uint32_t*)c) == *((const uint32_t*)col.c)); } template <> inline bool TColor::operator!=(const TColor& col) const { return (*((const uint32_t*)c) != *((const uint32_t*)col.c)); } template <> inline uint32_t TColor::toDWORD() const { return *((const uint32_t*)c); } /*----------------------------------------------------------------*/ typedef TColor Color8U; typedef TColor Color32F; typedef TColor Color64F; /*----------------------------------------------------------------*/ // structure containing the image pixels typedef Point2i ImageRef; template class TImage : public TDMatrix { public: typedef TYPE Type; typedef TDMatrix Base; typedef cv::Size Size; typedef typename Base::Base BaseBase; using Base::rows; using Base::cols; using Base::data; public: inline TImage() {} inline TImage(const Base& rhs) : Base(rhs) {} inline TImage(const cv::Mat& rhs) : Base(rhs) {} inline TImage(const cv::MatExpr& rhs) : Base(rhs) {} inline TImage(int _rows, int _cols) : Base(_rows, _cols) {} inline TImage(const Size& sz) : Base(sz) {} inline TImage(const Size& sz, const TYPE& v) : Base(sz, v) {} inline TImage(const Size& sz, TYPE* _data, size_t _step=Base::AUTO_STEP) : Base(sz.height, sz.width, _data, _step) {} #ifdef _SUPPORT_CPP11 inline TImage(cv::Mat&& rhs) : Base(std::forward(rhs)) {} inline TImage& operator = (cv::Mat&& rhs) { BaseBase::operator=(std::forward(rhs)); return *this; } #endif inline TImage& operator = (const Base& rhs) { BaseBase::operator=(rhs); return *this; } inline TImage& operator = (const BaseBase& rhs) { BaseBase::operator=(rhs); return *this; } inline TImage& operator = (const cv::MatExpr& rhs) { BaseBase::operator=(rhs); return *this; } /// What is the image size? inline int width() const { return cols; } inline int height() const { return rows; } /// What is the pixel stride of the image? inline size_t pixel_stride() const { return Base::elem_stride(); } inline const TYPE& getPixel(int y, int x) const; template TYPE sample(const TPoint2& pt) const; template TYPE sampleSafe(const TPoint2& pt) const; template bool sample(TV& v, const TPoint2& pt, const Functor& functor) const; template bool sampleSafe(TV& v, const TPoint2& pt, const Functor& functor) const; template TYPE sample(const TPoint2& pt, const Functor& functor, const TYPE& dv) const; template TYPE sampleSafe(const TPoint2& pt, const Functor& functor, const TYPE& dv) const; template INTERTYPE sample(const SAMPLER& sampler, const TPoint2& pt) const; template void toGray(TImage& out, int code, bool bNormalize=false, bool bSRGB=false) const; static cv::Size computeResize(const cv::Size& size, REAL scale); static cv::Size computeResize(const cv::Size& size, REAL scale, unsigned resizes); unsigned computeMaxResolution(unsigned& level, unsigned minImageSize=320, unsigned maxImageSize=INT_MAX) const; static unsigned computeMaxResolution(unsigned width, unsigned height, unsigned& level, unsigned minImageSize=320, unsigned maxImageSize=INT_MAX); template static void RasterizeTriangle(const TPoint2& v1, const TPoint2& v2, const TPoint2& v3, PARSER& parser); template static void RasterizeTriangleBary(const TPoint2& v1, const TPoint2& v2, const TPoint2& v3, PARSER& parser); template static void RasterizeTriangleDepth(TPoint3 p1, TPoint3 p2, TPoint3 p3, PARSER& parser); template static void DrawLine(const TPoint2& p1, const TPoint2& p2, PARSER& parser); typedef void (STCALL *FncDrawPointAntialias) (const ImageRef&, const ImageRef&, float, float, void*); static bool DrawLineAntialias(Point2f x1, Point2f x2, FncDrawPointAntialias fncDrawPoint, void* pData=NULL); static bool DrawLineAntialias(const ImageRef& x1, const ImageRef& x2, FncDrawPointAntialias fncDrawPoint, void* pData=NULL); template void DilateMean(TImage& out, const TYPE& invalid) const; bool Load(const String&); bool Save(const String&) const; #ifndef _RELEASE void Show(const String& winname, int delay=0, bool bDestroy=true) const; #endif #ifdef _USE_BOOST // serialize template void serialize(Archive& ar, const unsigned int /*version*/) { ar & boost::serialization::base_object(*this); } #endif }; /*----------------------------------------------------------------*/ typedef TImage Image8U; typedef TImage Image16U; typedef TImage Image16F; typedef TImage Image32F; typedef TImage Image64F; typedef TImage Image8U3; typedef TImage Image8U4; typedef TImage Image32F3; typedef TImage Image32F4; /*----------------------------------------------------------------*/ template class TBitMatrix { public: typedef TYPE Type; typedef cv::Size Size; struct Index { size_t idx; Type flag; inline Index() {} inline Index(size_t _idx, Type _flag) : idx(_idx), flag(_flag) {} }; enum { numBitsPerCell = sizeof(Type)*8 }; enum { numBitsShift = LOG2I() }; public: inline TBitMatrix() : data(NULL) {} inline TBitMatrix(int _rows, int _cols=1) : rows(_rows), cols(_cols), data(rows && cols ? new Type[computeLength(rows, cols)] : NULL) {} inline TBitMatrix(int _rows, int _cols, uint8_t v) : rows(_rows), cols(_cols), data(rows && cols ? new Type[computeLength(rows, cols)] : NULL) { if (!empty()) memset(v); } inline TBitMatrix(const Size& sz) : rows(sz.height), cols(sz.width), data(rows && cols ? new Type[computeLength(sz)] : NULL) {} inline TBitMatrix(const Size& sz, uint8_t v) : rows(sz.height), cols(sz.width), data(rows && cols ? new Type[computeLength(sz)] : NULL) { if (!empty()) memset(v); } inline ~TBitMatrix() { delete[] data; } inline void create(int _rows, int _cols=1) { if (!empty() && rows == _rows && cols == _cols) return; rows = _rows; cols = _cols; if (rows <=0 || cols <= 0) { release(); return; } delete[] data; data = new Type[length()]; } inline void create(const Size& sz) { create(sz.height, sz.width); } inline void release() { delete[] data; data = NULL; } inline void memset(uint8_t v) { ASSERT(!empty()); ::memset(data, v, sizeof(Type)*length()); } inline void swap(TBitMatrix& m) { union {int i; Type* d;} tmp; tmp.i = rows; rows = m.rows; m.rows = tmp.i; tmp.i = cols; cols = m.cols; m.cols = tmp.i; tmp.d = data; data = m.data; m.data = tmp.d; } inline void And(const TBitMatrix& m) { ASSERT(rows == m.rows && cols == m.cols); int i = length(); while (i-- > 0) data[i] &= m.data[i]; } inline void Or(const TBitMatrix& m) { ASSERT(rows == m.rows && cols == m.cols); int i = length(); while (i-- > 0) data[i] |= m.data[i]; } inline void XOr(const TBitMatrix& m) { ASSERT(rows == m.rows && cols == m.cols); int i = length(); while (i-- > 0) data[i] ^= m.data[i]; } inline bool empty() const { return data == NULL; } inline Size size() const { return Size(cols, rows); } inline int area() const { return cols*rows; } inline int length() const { return computeLength(rows, cols); } inline bool operator() (int i) const { return isSet(i); } inline bool operator() (int i, int j) const { return isSet(i,j); } inline bool operator() (const ImageRef& ir) const { return isSet(ir); } inline bool isSet(int i) const { ASSERT(!empty() && i=0 && pt.height>=0 && pt.width inline bool isInside(const cv::Point_& pt) const { return int(pt.x)>=0 && int(pt.y)>=0 && int(pt.x)=border && pt.height>=border && pt.width inline bool isInsideWithBorder(const cv::Point_& pt, int border) const { return int(pt.x)>=border && int(pt.y)>=border && int(pt.x) inline bool isInsideWithBorder(const cv::Point_& pt) const { return int(pt.x)>=border && int(pt.y)>=border && int(pt.x)>numBitsShift; } static inline int computeLength(int _rows, int _cols) { return computeLength(_rows*_cols); } static inline int computeLength(const Size& sz) { return computeLength(sz.area()); } static inline Index computeIndex(int i) { return Index(i>>numBitsShift, Type(1)<<(i&(numBitsPerCell-1))); } static inline Index computeIndex(int i, int j, int stride) { return computeIndex(i*stride+j); } static inline Index computeIndex(const ImageRef& ir, int stride) { return computeIndex(ir.y*stride+ir.x); } //! the number of rows and columns int rows, cols; //! pointer to the data Type* data; #ifdef _USE_BOOST protected: // implement BOOST serialization friend class boost::serialization::access; template void save(Archive& ar, const unsigned int /*version*/) const { if (empty()) { const int sz(0); ar & sz; return; } ar & cols; ar & rows; ar & boost::serialization::make_array(data, length()); } template void load(Archive& ar, const unsigned int /*version*/) { release(); ar & cols; if (cols == 0) return; ar & rows; create(rows, cols); ar & boost::serialization::make_array(data, length()); } BOOST_SERIALIZATION_SPLIT_MEMBER() #endif }; /*----------------------------------------------------------------*/ typedef TBitMatrix BitMatrix; /*----------------------------------------------------------------*/ // weighted accumulator class that operates on arbitrary types template struct TAccumulator { typedef TYPE Type; typedef ACCUMTYPE AccumType; typedef WEIGHTTYPE WeightType; AccumType value; WeightType weight; inline TAccumulator() : value(INITTO(static_cast(NULL), 0)), weight(0) {} inline TAccumulator(const Type& v, const WeightType& w) : value(v), weight(w) {} inline bool IsEmpty() const { return weight <= 0; } // adds the given weighted value to the internal value inline void Add(const Type& v, const WeightType& w) { value += v*w; weight += w; } inline TAccumulator& operator +=(const TAccumulator& accum) { value += accum.value; weight += accum.weight; return *this; } inline TAccumulator operator +(const TAccumulator& accum) const { return TAccumulator( value + accum.value, weight + accum.weight ); } // subtracts the given weighted value to the internal value inline void Sub(const Type& v, const WeightType& w) { value -= v*w; weight -= w; } inline TAccumulator& operator -=(const TAccumulator& accum) { value -= accum.value; weight -= accum.weight; return *this; } inline TAccumulator operator -(const TAccumulator& accum) const { return TAccumulator( value - accum.value, weight - accum.weight ); } // returns the normalized version of the internal value inline AccumType NormalizedFull() const { return value / weight; } inline Type Normalized() const { return Type(NormalizedFull()); } #ifdef _USE_BOOST // implement BOOST serialization template void serialize(Archive& ar, const unsigned int /*version*/) { ar & value; ar & weight; } #endif }; /*----------------------------------------------------------------*/ // structure used for sorting some indices by their score (decreasing by default) template struct TIndexScore { IndexType idx; ScoreType score; inline TIndexScore() {} inline TIndexScore(IndexType _idx, ScoreType _score) : idx(_idx), score(_score) {} // compare by index (increasing) inline bool operator<(IndexType i) const { return (idx < i); } inline bool operator==(IndexType i) const { return (idx == i); } // compare by score (decreasing) inline bool operator<(const TIndexScore& r) const { return (score > r.score); } inline bool operator==(const TIndexScore& r) const { return (score == r.score); } static bool STCALL CompareByIndex(const TIndexScore& l, const TIndexScore& r) { return (l.idx < r.idx); } static bool STCALL CompareByScore(const TIndexScore& l, const TIndexScore& r) { return (r.score < l.score); } #ifdef _USE_BOOST // implement BOOST serialization template void serialize(Archive& ar, const unsigned int /*version*/) { ar & idx; ar & score; } #endif }; /*----------------------------------------------------------------*/ typedef TIndexScore IndexScore; typedef CLISTDEF0(IndexScore) IndexScoreArr; /*----------------------------------------------------------------*/ // structure describing a pair of indices as one long index struct PairIdx { typedef uint64_t PairIndex; typedef uint32_t Index; union { PairIndex idx; Index indices[2]; struct { #if __BYTE_ORDER == __LITTLE_ENDIAN Index j; Index i; #else Index i; Index j; #endif }; }; inline PairIdx() {} inline PairIdx(PairIndex _idx) : idx(_idx) {} inline PairIdx(Index _i, Index _j) #if __BYTE_ORDER == __LITTLE_ENDIAN : j(_j), i(_i) {} #else : i(_i), j(_j) {} #endif // get index inline operator PairIndex () const { return idx; } inline Index operator[](unsigned n) const { ASSERT(n < 2); #if __BYTE_ORDER == __LITTLE_ENDIAN return indices[(n+1)%2]; #else return indices[n]; #endif } inline Index& operator[](unsigned n) { ASSERT(n < 2); #if __BYTE_ORDER == __LITTLE_ENDIAN return indices[(n+1)%2]; #else return indices[n]; #endif } // compare by index (increasing) inline bool operator<(const PairIdx& r) const { return (idx < r.idx); } inline bool operator==(const PairIdx& r) const { return (idx == r.idx); } }; /*----------------------------------------------------------------*/ typedef CLISTDEF0(PairIdx) PairIdxArr; inline PairIdx MakePairIdx(uint32_t idxImageA, uint32_t idxImageB) { return (idxImageA inline String cvMat2String(const TMatrix& mat, LPCSTR format="% 10.4f ") { return cvMat2String(cv::Mat(mat), format); } template inline String cvMat2String(const TPoint3& pt, LPCSTR format="% 10.4f ") { return cvMat2String(cv::Mat(pt), format); } /*----------------------------------------------------------------*/ } // namespace SEACAVE #ifdef _USE_EIGEN // Implement SO3 and SO2 lie groups // as in TooN library: https://github.com/edrosten/TooN // Copyright (C) 2005,2009 Tom Drummond (twd20@cam.ac.uk) namespace Eigen { /// Class to represent a three-dimensional rotation matrix. Three-dimensional rotation /// matrices are members of the Special Orthogonal Lie group SO3. This group can be parameterized /// three numbers (a vector in the space of the Lie Algebra). In this class, the three parameters are the /// finite rotation vector, i.e. a three-dimensional vector whose direction is the axis of rotation /// and whose length is the angle of rotation in radians. Exponentiating this vector gives the matrix, /// and the logarithm of the matrix gives this vector. template class SO3 { public: template friend std::istream& operator>>(std::istream& is, SO3

& rhs); typedef Matrix Mat3; typedef Matrix Vec3; /// Default constructor. Initializes the matrix to the identity (no rotation) inline SO3() : mat(Mat3::Identity()) {} /// Construct from a rotation matrix. inline SO3(const Mat3& rhs) : mat(rhs) {} /// Construct from the axis of rotation (and angle given by the magnitude). inline SO3(const Vec3& v) : mat(exp(v)) {} /// creates an SO3 as a rotation that takes Vector a into the direction of Vector b /// with the rotation axis along a ^ b. If |a ^ b| == 0, it creates the identity rotation. /// An assertion will fail if Vector a and Vector b are in exactly opposite directions. /// @param a source Vector /// @param b target Vector SO3(const Vec3& a, const Vec3& b) { ASSERT(a.size() == 3); ASSERT(b.size() == 3); Vec3 n(a.cross(b)); const Precision nrmSq(n.squaredNorm()); if (nrmSq == Precision(0)) { // check that the vectors are in the same direction if cross product is 0; if not, // this means that the rotation is 180 degrees, which leads to an ambiguity in the rotation axis ASSERT(a.dot(b) >= Precision(0)); mat = Mat3::Identity(); return; } n *= Precision(1)/sqrt(nrmSq); Mat3 R1; R1.col(0) = a.normalized(); R1.col(1) = n; R1.col(2) = R1.col(0).cross(n); mat.col(0) = b.normalized(); mat.col(1) = n; mat.col(2) = mat.col(0).cross(n); mat = mat * R1.transpose(); } /// Assignment operator from a general matrix. This also calls coerce() /// to make sure that the matrix is a valid rotation matrix. inline SO3& operator=(const Mat3& rhs) { mat = rhs; coerce(); return *this; } /// Modifies the matrix to make sure it is a valid rotation matrix. void coerce() { mat.row(0).normalize(); const Precision d01(mat.row(0).dot(mat.row(1))); mat.row(1) -= mat.row(0) * d01; mat.row(1).normalize(); const Precision d02(mat.row(0).dot(mat.row(2))); mat.row(2) -= mat.row(0) * d02; const Precision d12(mat.row(1).dot(mat.row(2))); mat.row(2) -= mat.row(1) * d12; mat.row(2).normalize(); // check for positive determinant <=> right handed coordinate system of row vectors ASSERT(mat.row(0).cross(mat.row(1)).dot(mat.row(2)) > 0); } /// Exponentiate a vector in the Lie algebra to generate a new SO3. /// See the Detailed Description for details of this vector. inline Mat3 exp(const Vec3& vect) const; /// Take the logarithm of the matrix, generating the corresponding vector in the Lie Algebra. /// See the Detailed Description for details of this vector. inline Vec3 ln() const; /// Right-multiply by another rotation matrix template inline SO3& operator *=(const SO3

& rhs) { *this = *this * rhs; return *this; } /// Right-multiply by another rotation matrix inline SO3 operator *(const SO3& rhs) const { return SO3(*this, rhs); } /// Returns the SO3 as a Matrix<3> inline const Mat3& get_matrix() const { return mat; } /// Returns the i-th generator. The generators of a Lie group are the basis /// for the space of the Lie algebra. For %SO3, the generators are three /// \f$3\times3\f$ matrices representing the three possible (linearized) /// rotations. inline static Mat3 generator(int i) { Mat3 result(Mat3::Zero()); result((i+1)%3,(i+2)%3) = Precision(-1); result((i+2)%3,(i+1)%3) = Precision( 1); return result; } /// Returns the i-th generator times pos inline static Vec3 generator_field(int i, const Vec3& pos) { Vec3 result; result(i) = Precision(0); result((i+1)%3) = -pos((i+2)%3); result((i+2)%3) = pos((i+1)%3); return result; } template inline SO3(const SO3& a, const SO3& b) : mat(a.get_matrix()*b.get_matrix()) {} protected: Mat3 mat; #ifdef _USE_BOOST // implement BOOST serialization friend class boost::serialization::access; template void save(Archive& ar, const unsigned int /*version*/) const { Vec3 comp(ln()); ar & comp; } template void load(Archive& ar, const unsigned int /*version*/) { Vec3 comp; ar & comp; mat = exp(comp); } BOOST_SERIALIZATION_SPLIT_MEMBER() #endif }; /*----------------------------------------------------------------*/ /// Class to represent a two-dimensional rotation matrix. Two-dimensional rotation /// matrices are members of the Special Orthogonal Lie group SO2. This group can be parameterized /// with one number (the rotation angle). template class SO2 { public: template friend std::istream& operator>>(std::istream&, SO2

&); typedef Matrix Mat2; /// Default constructor. Initializes the matrix to the identity (no rotation) inline SO2() : mat(Mat2::Identity()) {} /// Construct from a rotation matrix. inline SO2(const Mat2& rhs) : mat(rhs) {} /// Construct from an angle. inline SO2(const Precision l) : mat(exp(l)) {} /// Assignment operator from a general matrix. This also calls coerce() /// to make sure that the matrix is a valid rotation matrix. inline SO2& operator=(const Mat2& rhs) { mat = rhs; coerce(); return *this; } /// Modifies the matrix to make sure it is a valid rotation matrix. inline void coerce() { mat.row(0).normalize(); mat.row(1) = (mat.row(1) - mat.row(0) * (mat.row(0).dot(mat.row(1)))).normalized(); } /// Exponentiate an angle in the Lie algebra to generate a new SO2. inline Mat2 exp(const Precision& d) const; /// extracts the rotation angle from the SO2 inline Precision ln() const; /// Self right-multiply by another rotation matrix inline SO2& operator *=(const SO2& rhs) { mat = mat*rhs.get_matrix(); return *this; } /// Right-multiply by another rotation matrix inline SO2 operator *(const SO2& rhs) const { return SO2(*this, rhs); } /// Returns the SO2 as a Matrix<2> inline const Mat2& get_matrix() const { return mat; } /// returns generator matrix inline static Mat2 generator() { Mat2 result; result(0,0) = Precision(0); result(0,1) = Precision(-1); result(1,0) = Precision(1); result(1,1) = Precision(0); return result; } protected: Mat2 mat; #ifdef _USE_BOOST // implement BOOST serialization friend class boost::serialization::access; template void save(Archive& ar, const unsigned int /*version*/) const { Precision comp(ln()); ar & comp; } template void load(Archive& ar, const unsigned int /*version*/) { Precision comp; ar & comp; mat = exp(comp); } BOOST_SERIALIZATION_SPLIT_MEMBER() #endif }; /*----------------------------------------------------------------*/ } // namespace Eigen #endif // _USE_EIGEN #include "../Math/LMFit/lmmin.h" #include "Types.inl" #include "Util.inl" #include "Rotation.h" #include "Sphere.h" #include "AABB.h" #include "OBB.h" #include "Plane.h" #include "Ray.h" #include "Line.h" #include "Octree.h" #include "UtilCUDA.h" #endif // __SEACAVE_TYPES_H__