2024-09-11 16:49:38 +08:00

541 lines
14 KiB
C++

/*
* 说明: 基本的数学图形函数
*
* 作者: 杨海洋
* 日期: 2023-03-15
*/
#ifndef GEOMETRY_H
#define GEOMETRY_H
#include "HCommon.h"
template<typename T> static inline T saturate_cast(unsigned char v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(char v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(unsigned short v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(short v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(unsigned int v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(int v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(float v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(double v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(long long v) { return T(v); }
/** @overload */
template<typename T> static inline T saturate_cast(unsigned long long v){ return T(v); }
template <typename T>
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<typename T2> operator PointT<T2>() const
{
return PointT<T2>(saturate_cast<T2>(x), saturate_cast<T2>(y));
}
//! dot product
T dot(const PointT& pt) const {return saturate_cast<T>(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<T>& r) const{ return r.contains(*this); };
public:
T x = 0, y = 0;
};
using Pointi = PointT<int>;
using Pointf = PointT<float>;
using Pointd = PointT<double>;
using Point = Pointi;
template<typename T> static inline
PointT<T>& operator += (PointT<T>& a, const PointT<T>& b)
{
a.x += b.x;
a.y += b.y;
return a;
}
template<typename T> static inline
PointT<T>& operator -= (PointT<T>& a, const PointT<T>& b)
{
a.x -= b.x;
a.y -= b.y;
return a;
}
template<typename T> static inline
PointT<T>& operator *= (PointT<T>& a, int b)
{
a.x = saturate_cast<T>(a.x * b);
a.y = saturate_cast<T>(a.y * b);
return a;
}
template<typename T> static inline
PointT<T>& operator *= (PointT<T>& a, float b)
{
a.x = saturate_cast<T>(a.x * b);
a.y = saturate_cast<T>(a.y * b);
return a;
}
template<typename T> static inline
PointT<T>& operator *= (PointT<T>& a, double b)
{
a.x = saturate_cast<T>(a.x * b);
a.y = saturate_cast<T>(a.y * b);
return a;
}
template<typename T> static inline
PointT<T>& operator /= (PointT<T>& a, int b)
{
a.x = saturate_cast<T>(a.x / b);
a.y = saturate_cast<T>(a.y / b);
return a;
}
template<typename T> static inline
PointT<T>& operator /= (PointT<T>& a, float b)
{
a.x = saturate_cast<T>(a.x / b);
a.y = saturate_cast<T>(a.y / b);
return a;
}
template<typename T> static inline
PointT<T>& operator /= (PointT<T>& a, double b)
{
a.x = saturate_cast<T>(a.x / b);
a.y = saturate_cast<T>(a.y / b);
return a;
}
template<typename T> static inline
double norm(const PointT<T>& pt)
{
return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y);
}
template<typename T> static inline
bool operator == (const PointT<T>& a, const PointT<T>& b)
{
return a.x == b.x && a.y == b.y;
}
template<typename T> static inline
bool operator != (const PointT<T>& a, const PointT<T>& b)
{
return a.x != b.x || a.y != b.y;
}
template<typename T> static inline
PointT<T> operator + (const PointT<T>& a, const PointT<T>& b)
{
return PointT<T>( saturate_cast<T>(a.x + b.x), saturate_cast<T>(a.y + b.y) );
}
template<typename T> static inline
PointT<T> operator - (const PointT<T>& a, const PointT<T>& b)
{
return PointT<T>( saturate_cast<T>(a.x - b.x), saturate_cast<T>(a.y - b.y) );
}
template<typename T> static inline
PointT<T> operator - (const PointT<T>& a)
{
return PointT<T>( saturate_cast<T>(-a.x), saturate_cast<T>(-a.y) );
}
template<typename T> static inline
PointT<T> operator * (const PointT<T>& a, int b)
{
return PointT<T>( saturate_cast<T>(a.x*b), saturate_cast<T>(a.y*b) );
}
template<typename T> static inline
PointT<T> operator * (int a, const PointT<T>& b)
{
return PointT<T>( saturate_cast<T>(b.x*a), saturate_cast<T>(b.y*a) );
}
template<typename T> static inline
PointT<T> operator * (const PointT<T>& a, float b)
{
return PointT<T>( saturate_cast<T>(a.x*b), saturate_cast<T>(a.y*b) );
}
template<typename T> static inline
PointT<T> operator * (float a, const PointT<T>& b)
{
return PointT<T>( saturate_cast<T>(b.x*a), saturate_cast<T>(b.y*a) );
}
template<typename T> static inline
PointT<T> operator * (const PointT<T>& a, double b)
{
return PointT<T>( saturate_cast<T>(a.x*b), saturate_cast<T>(a.y*b) );
}
template<typename T> static inline
PointT<T> operator * (double a, const PointT<T>& b)
{
return PointT<T>( saturate_cast<T>(b.x*a), saturate_cast<T>(b.y*a) );
}
template<typename T> static inline
PointT<T> operator / (const PointT<T>& a, int b)
{
PointT<T> tmp(a);
tmp /= b;
return tmp;
}
template<typename T> static inline
PointT<T> operator / (const PointT<T>& a, float b)
{
PointT<T> tmp(a);
tmp /= b;
return tmp;
}
template<typename T> static inline
PointT<T> operator / (const PointT<T>& a, double b)
{
PointT<T> tmp(a);
tmp /= b;
return tmp;
}
template<typename T>
class LineT
{
public:
virtual ~LineT(){}
LineT(){}
LineT(const PointT<T>& _p1, const PointT<T>& _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<typename T2> operator LineT<T2>() const
{
return LineT<T2>(PointT<T>(saturate_cast<T2>(p1.x), saturate_cast<T2>(p1.y)),
PointT<T>(saturate_cast<T2>(p2.x), saturate_cast<T2>(p2.y)));
}
T distance(const PointT<T>& p1, const PointT<T>& p2)
{
return saturate_cast<T>(std::sqrt(std::pow(p1.x-p2.x,2),std::pow(p1.y-p2.y,2)));
}
public:
PointT<T> p1, p2;
};
using Linei = LineT<int>;
using Linef = LineT<float>;
using Lined = LineT<double>;
using Line = Linei;
template<typename T>
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<T>& 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<typename T2> operator SizeT<T2>() const
{
return SizeT<T2>(saturate_cast<T2>(width), saturate_cast<T2>(height));
};
public:
T width; //!< the width
T height; //!< the height
};
using Sizei = SizeT<int>;
using Sizef = SizeT<float>;
using Sized = SizeT<double>;
using Size = Sizei;
template<typename T> static inline
SizeT<T>& operator *= (SizeT<T>& a, T b)
{
a.width *= b;
a.height *= b;
return a;
}
template<typename T> static inline
SizeT<T> operator * (const SizeT<T>& a, T b)
{
SizeT<T> tmp(a);
tmp *= b;
return tmp;
}
template<typename T> static inline
SizeT<T>& operator /= (SizeT<T>& a, T b)
{
a.width /= b;
a.height /= b;
return a;
}
template<typename T> static inline
SizeT<T> operator / (const SizeT<T>& a, T b)
{
SizeT<T> tmp(a);
tmp /= b;
return tmp;
}
template<typename T> static inline
SizeT<T>& operator += (SizeT<T>& a, const SizeT<T>& b)
{
a.width += b.width;
a.height += b.height;
return a;
}
template<typename T> static inline
SizeT<T> operator + (const SizeT<T>& a, const SizeT<T>& b)
{
SizeT<T> tmp(a);
tmp += b;
return tmp;
}
template<typename T> static inline
SizeT<T>& operator -= (SizeT<T>& a, const SizeT<T>& b)
{
a.width -= b.width;
a.height -= b.height;
return a;
}
template<typename T> static inline
SizeT<T> operator - (const SizeT<T>& a, const SizeT<T>& b)
{
SizeT<T> tmp(a);
tmp -= b;
return tmp;
}
template<typename T> static inline
bool operator == (const SizeT<T>& a, const SizeT<T>& b)
{
return a.width == b.width && a.height == b.height;
}
template<typename T> static inline
bool operator != (const SizeT<T>& a, const SizeT<T>& b)
{
return !(a == b);
}
template<typename T> 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<T>& org, const SizeT<T>& z) : x(org.x), y(org.y), width(z.width), height(z.height) {}
RectT(const PointT<T>& pt1, const PointT<T>& 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<T> tl() const { return PointT<T>(x,y); }
//! the bottom-right corner
PointT<T> br() const{ return PointT<T>(x + width, y + height); }
//! size (width, height) of the rectangle
SizeT<T> size() const { return SizeT<T>(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<typename T2> operator RectT<T2>() const
{
return RectT<T2>(saturate_cast<T2>(x), saturate_cast<T2>(y), saturate_cast<T2>(width), saturate_cast<T2>(height));
}
//! checks whether the rectangle contains the point
bool contains(const PointT<T>& 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<int> ;
using Rect2f = RectT<float> ;
using Rect2d = RectT<double> ;
using Rect = Rect2i ;
template<typename T> static inline
RectT<T>& operator += ( RectT<T>& a, const PointT<T>& b )
{
a.x += b.x;
a.y += b.y;
return a;
}
template<typename T> static inline
RectT<T>& operator -= ( RectT<T>& a, const PointT<T>& b )
{
a.x -= b.x;
a.y -= b.y;
return a;
}
template<typename T> static inline
RectT<T>& operator += ( RectT<T>& a, const SizeT<T>& b )
{
a.width += b.width;
a.height += b.height;
return a;
}
template<typename T> static inline
RectT<T>& operator -= ( RectT<T>& a, const SizeT<T>& b )
{
const T width = a.width - b.width;
const T height = a.height - b.height;
a.width = width;
a.height = height;
return a;
}
template<typename T> static inline
RectT<T>& operator &= ( RectT<T>& a, const RectT<T>& 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<typename T> static inline
RectT<T>& operator |= ( RectT<T>& a, const RectT<T>& 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<typename T> static inline
bool operator == (const RectT<T>& a, const RectT<T>& b)
{
return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height;
}
template<typename T> static inline
bool operator != (const RectT<T>& a, const RectT<T>& b)
{
return a.x != b.x || a.y != b.y || a.width != b.width || a.height != b.height;
}
template<typename T> static inline
RectT<T> operator + (const RectT<T>& a, const PointT<T>& b)
{
return RectT<T>( a.x + b.x, a.y + b.y, a.width, a.height );
}
template<typename T> static inline
RectT<T> operator - (const RectT<T>& a, const PointT<T>& b)
{
return RectT<T>( a.x - b.x, a.y - b.y, a.width, a.height );
}
template<typename T> static inline
RectT<T> operator + (const RectT<T>& a, const SizeT<T>& b)
{
return RectT<T>( a.x, a.y, a.width + b.width, a.height + b.height );
}
template<typename T> static inline
RectT<T> operator - (const RectT<T>& a, const SizeT<T>& b)
{
const T width = a.width - b.width;
const T height = a.height - b.height;
return RectT<T>( a.x, a.y, width, height );
}
template<typename T> static inline
RectT<T> operator & (const RectT<T>& a, const RectT<T>& b)
{
RectT<T> c = a;
return c &= b;
}
template<typename T> static inline
RectT<T> operator | (const RectT<T>& a, const RectT<T>& b)
{
RectT<T> 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