/* * 说明: 基本的数学图形函数 * * 作者: 杨海洋 * 日期: 2023-03-15 */ #ifndef GEOMETRY_H #define GEOMETRY_H #include "HCommon.h" template static inline T saturate_cast(unsigned char v) { return T(v); } /** @overload */ template static inline T saturate_cast(char v) { return T(v); } /** @overload */ template static inline T saturate_cast(unsigned short v) { return T(v); } /** @overload */ template static inline T saturate_cast(short v) { return T(v); } /** @overload */ template static inline T saturate_cast(unsigned int v) { return T(v); } /** @overload */ template static inline T saturate_cast(int v) { return T(v); } /** @overload */ template static inline T saturate_cast(float v) { return T(v); } /** @overload */ template static inline T saturate_cast(double v) { return T(v); } /** @overload */ template static inline T saturate_cast(long long v) { return T(v); } /** @overload */ template static inline T saturate_cast(unsigned long long v){ return T(v); } template class PointT { public: JUDGE_JSON_NLOHMANN_DEFINE(PointT,x,y); virtual ~PointT(){} PointT():x(0), y(0) {} PointT(T _x, T _y):x(_x), y(_y) {} PointT(const PointT& pt):x(pt.x), y(pt.y) {} PointT& operator = (const PointT& pt) { x=pt.x; y=pt.y; return *this; } //! conversion to another data type template operator PointT() const { return PointT(saturate_cast(x), saturate_cast(y)); } //! dot product T dot(const PointT& pt) const {return saturate_cast(x*pt.x + y*pt.y);} //! dot product computed in double-precision arithmetics double ddot(const PointT& pt) const{return (double)x*(double)(pt.x) + (double)y*(double)(pt.y);} //! cross-product double cross(const PointT& pt) const{return (double)x*pt.y - (double)y*pt.x;} //! checks whether the point is inside the specified rectangle //bool inside(const RectT& r) const{ return r.contains(*this); }; public: T x = 0, y = 0; }; using Pointi = PointT; using Pointf = PointT; using Pointd = PointT; using Point = Pointi; template static inline PointT& operator += (PointT& a, const PointT& b) { a.x += b.x; a.y += b.y; return a; } template static inline PointT& operator -= (PointT& a, const PointT& b) { a.x -= b.x; a.y -= b.y; return a; } template static inline PointT& operator *= (PointT& a, int b) { a.x = saturate_cast(a.x * b); a.y = saturate_cast(a.y * b); return a; } template static inline PointT& operator *= (PointT& a, float b) { a.x = saturate_cast(a.x * b); a.y = saturate_cast(a.y * b); return a; } template static inline PointT& operator *= (PointT& a, double b) { a.x = saturate_cast(a.x * b); a.y = saturate_cast(a.y * b); return a; } template static inline PointT& operator /= (PointT& a, int b) { a.x = saturate_cast(a.x / b); a.y = saturate_cast(a.y / b); return a; } template static inline PointT& operator /= (PointT& a, float b) { a.x = saturate_cast(a.x / b); a.y = saturate_cast(a.y / b); return a; } template static inline PointT& operator /= (PointT& a, double b) { a.x = saturate_cast(a.x / b); a.y = saturate_cast(a.y / b); return a; } template static inline double norm(const PointT& pt) { return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y); } template static inline bool operator == (const PointT& a, const PointT& b) { return a.x == b.x && a.y == b.y; } template static inline bool operator != (const PointT& a, const PointT& b) { return a.x != b.x || a.y != b.y; } template static inline PointT operator + (const PointT& a, const PointT& b) { return PointT( saturate_cast(a.x + b.x), saturate_cast(a.y + b.y) ); } template static inline PointT operator - (const PointT& a, const PointT& b) { return PointT( saturate_cast(a.x - b.x), saturate_cast(a.y - b.y) ); } template static inline PointT operator - (const PointT& a) { return PointT( saturate_cast(-a.x), saturate_cast(-a.y) ); } template static inline PointT operator * (const PointT& a, int b) { return PointT( saturate_cast(a.x*b), saturate_cast(a.y*b) ); } template static inline PointT operator * (int a, const PointT& b) { return PointT( saturate_cast(b.x*a), saturate_cast(b.y*a) ); } template static inline PointT operator * (const PointT& a, float b) { return PointT( saturate_cast(a.x*b), saturate_cast(a.y*b) ); } template static inline PointT operator * (float a, const PointT& b) { return PointT( saturate_cast(b.x*a), saturate_cast(b.y*a) ); } template static inline PointT operator * (const PointT& a, double b) { return PointT( saturate_cast(a.x*b), saturate_cast(a.y*b) ); } template static inline PointT operator * (double a, const PointT& b) { return PointT( saturate_cast(b.x*a), saturate_cast(b.y*a) ); } template static inline PointT operator / (const PointT& a, int b) { PointT tmp(a); tmp /= b; return tmp; } template static inline PointT operator / (const PointT& a, float b) { PointT tmp(a); tmp /= b; return tmp; } template static inline PointT operator / (const PointT& a, double b) { PointT tmp(a); tmp /= b; return tmp; } template class LineT { public: virtual ~LineT(){} LineT(){} LineT(const PointT& _p1, const PointT& _p2):p1(_p1), p2(_p2) {} LineT(const LineT& l) : p1(l.p1), p2(l.p2) {} LineT& operator = (const LineT& l) { p1=l.p1; p2=l.p2; return *this; } template operator LineT() const { return LineT(PointT(saturate_cast(p1.x), saturate_cast(p1.y)), PointT(saturate_cast(p2.x), saturate_cast(p2.y))); } T distance(const PointT& p1, const PointT& p2) { return saturate_cast(std::sqrt(std::pow(p1.x-p2.x,2),std::pow(p1.y-p2.y,2))); } public: PointT p1, p2; }; using Linei = LineT; using Linef = LineT; using Lined = LineT; using Line = Linei; template class SizeT { public: SizeT():width(0),height(0){} SizeT(T _width, T _height):width(_width),height(_height){}; SizeT(const SizeT& z):width(z.width),height(z.height){}; SizeT(const PointT& pt):width(pt.x), height(pt.y){}; SizeT& operator = (const SizeT& z) { width = z.width; height=z.height; return *this;}; //! the area (width*height) T area() const { return width * height; }; //! true if empty bool empty() const {return width <= 0 || height <= 0;} //! conversion of another data type. template operator SizeT() const { return SizeT(saturate_cast(width), saturate_cast(height)); }; public: T width; //!< the width T height; //!< the height }; using Sizei = SizeT; using Sizef = SizeT; using Sized = SizeT; using Size = Sizei; template static inline SizeT& operator *= (SizeT& a, T b) { a.width *= b; a.height *= b; return a; } template static inline SizeT operator * (const SizeT& a, T b) { SizeT tmp(a); tmp *= b; return tmp; } template static inline SizeT& operator /= (SizeT& a, T b) { a.width /= b; a.height /= b; return a; } template static inline SizeT operator / (const SizeT& a, T b) { SizeT tmp(a); tmp /= b; return tmp; } template static inline SizeT& operator += (SizeT& a, const SizeT& b) { a.width += b.width; a.height += b.height; return a; } template static inline SizeT operator + (const SizeT& a, const SizeT& b) { SizeT tmp(a); tmp += b; return tmp; } template static inline SizeT& operator -= (SizeT& a, const SizeT& b) { a.width -= b.width; a.height -= b.height; return a; } template static inline SizeT operator - (const SizeT& a, const SizeT& b) { SizeT tmp(a); tmp -= b; return tmp; } template static inline bool operator == (const SizeT& a, const SizeT& b) { return a.width == b.width && a.height == b.height; } template static inline bool operator != (const SizeT& a, const SizeT& b) { return !(a == b); } template class RectT { public: RectT(): x(0), y(0), width(0), height(0) {} RectT(T _x, T _y, T _width, T _height): x(_x), y(_y), width(_width), height(_height) {} RectT(const RectT& r) : x(r.x), y(r.y), width(r.width), height(r.height) {} RectT(const PointT& org, const SizeT& z) : x(org.x), y(org.y), width(z.width), height(z.height) {} RectT(const PointT& pt1, const PointT& pt2) { x = std::min(pt1.x, pt2.x); y = std::min(pt1.y, pt2.y); width = std::max(pt1.x, pt2.x) - x; height = std::max(pt1.y, pt2.y) - y; } T& operator = ( const RectT& r ){x = r.x;y = r.y;width = r.width;height = r.height; return *this;} //! the top-left corner PointT tl() const { return PointT(x,y); } //! the bottom-right corner PointT br() const{ return PointT(x + width, y + height); } //! size (width, height) of the rectangle SizeT size() const { return SizeT(width, height); } //! area (width*height) of the rectangle T area() const { return width * height; }; //! true if empty bool empty() const {return width <= 0 || height <= 0;}; //! conversion to another data type template operator RectT() const { return RectT(saturate_cast(x), saturate_cast(y), saturate_cast(width), saturate_cast(height)); } //! checks whether the rectangle contains the point bool contains(const PointT& pt) const {return x <= pt.x && pt.x < x + width && y <= pt.y && pt.y < y + height;}; public: T x; //!< x coordinate of the top-left corner T y; //!< y coordinate of the top-left corner T width; //!< width of the rectangle T height; //!< height of the rectangle }; using Rect2i = RectT ; using Rect2f = RectT ; using Rect2d = RectT ; using Rect = Rect2i ; template static inline RectT& operator += ( RectT& a, const PointT& b ) { a.x += b.x; a.y += b.y; return a; } template static inline RectT& operator -= ( RectT& a, const PointT& b ) { a.x -= b.x; a.y -= b.y; return a; } template static inline RectT& operator += ( RectT& a, const SizeT& b ) { a.width += b.width; a.height += b.height; return a; } template static inline RectT& operator -= ( RectT& a, const SizeT& b ) { const T width = a.width - b.width; const T height = a.height - b.height; a.width = width; a.height = height; return a; } template static inline RectT& operator &= ( RectT& a, const RectT& b ) { T x1 = std::max(a.x, b.x); T y1 = std::max(a.y, b.y); a.width = std::min(a.x + a.width, b.x + b.width) - x1; a.height = std::min(a.y + a.height, b.y + b.height) - y1; a.x = x1; a.y = y1; if( a.width <= 0 || a.height <= 0 ) a = Rect(); return a; } template static inline RectT& operator |= ( RectT& a, const RectT& b ) { if (a.empty()) { a = b; } else if (!b.empty()) { T x1 = std::min(a.x, b.x); T y1 = std::min(a.y, b.y); a.width = std::max(a.x + a.width, b.x + b.width) - x1; a.height = std::max(a.y + a.height, b.y + b.height) - y1; a.x = x1; a.y = y1; } return a; } template static inline bool operator == (const RectT& a, const RectT& b) { return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height; } template static inline bool operator != (const RectT& a, const RectT& b) { return a.x != b.x || a.y != b.y || a.width != b.width || a.height != b.height; } template static inline RectT operator + (const RectT& a, const PointT& b) { return RectT( a.x + b.x, a.y + b.y, a.width, a.height ); } template static inline RectT operator - (const RectT& a, const PointT& b) { return RectT( a.x - b.x, a.y - b.y, a.width, a.height ); } template static inline RectT operator + (const RectT& a, const SizeT& b) { return RectT( a.x, a.y, a.width + b.width, a.height + b.height ); } template static inline RectT operator - (const RectT& a, const SizeT& b) { const T width = a.width - b.width; const T height = a.height - b.height; return RectT( a.x, a.y, width, height ); } template static inline RectT operator & (const RectT& a, const RectT& b) { RectT c = a; return c &= b; } template static inline RectT operator | (const RectT& a, const RectT& b) { RectT c = a; return c |= b; } struct GPS { GPS():sn(0), se(0){} GPS(double _sn, double _se):sn(_sn), se(_se){} GPS(const GPS& gps):sn(gps.sn), se(gps.se){} GPS& operator = (const GPS& g) { sn=g.sn; se=g.se; return *this; } double sn = 0, se = 0; //纬度, 经度 }; #endif // GEOMETRY_H