541 lines
14 KiB
C++
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
|