点
1、注意 ^ 运算符的优先级是很低的。
2、注意重合点和共线点的情况
const double eps = 1e-9;
const double PI = acos(-1.0);
int sgn(double x) {
return (abs(x) <= eps) ? 0 : (x > 0 ? 1 : -1);
}
struct Point {
double x, y;
Point() {}
Point(double x, double y): x(x), y(y) {}
double len() {
return sqrt(x * x + y * y);
}
friend Point operator+(const Point &a, const Point &b) {
return Point(a.x + b.x, a.y + b.y);
}
friend Point operator-(const Point &a, const Point &b) {
return Point(a.x - b.x, a.y - b.y);
}
friend Point operator*(const Point &p, const double &k) {
return Point(k * p.x, k * p.y);
}
friend Point operator*(const double &k, const Point &p) {
return Point(k * p.x, k * p.y);
}
friend bool operator==(const Point &a, const Point &b) {
return (sgn(a.x - b.x) == 0) && (sgn(a.y - b.y) == 0);
}
friend double operator*(const Point &a, const Point &b) {
return a.x * b.x + a.y * b.y;
}
friend double operator^(const Point &a, const Point &b) {
return a.x * b.y - a.y * b.x;
}
friend double dis(const Point &a, const Point &b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
//返回绕原点旋转A弧度的结果
Point Rotate(const double &A) {
return Point(x * cos(A) - y * sin(A), x * sin(A) + y * cos(A));
}
};
线段/直线
struct Segment {
Point s, t;
Segment() {}
Segment(const Point &s, const Point &t): s(s), t(t) {}
//返回点到线段的距离
double PointDistanceWithSegment(const Point &p) {
if(sgn((p - s) * (t - s)) < 0)
return (p - s).len();
if(sgn((p - t) * (s - t)) < 0)
return (p - t).len();
return abs((s - p) ^ (t - p)) / dis(s, t);
}
//返回点到直线的投影
Point PointProjectToLine(const Point &p) {
double r = ((t - s) * (p - s)) / ((t - s) * (t - s));
return s + r * (t - s);
}
//判断点是否在线段上
bool PointOnSegment(const Point &p) {
return (sgn((p - s) ^ (t - s)) == 0) && (sgn((p - s) * (p - t)) <= 0);
}
//判断两条直线是否平行
bool LineParallelWithLine(const Segment &l) {
return !sgn((s - t) ^ (l.s - l.t));
}
};
还差一个直线交点和直线向法向量方向平移。
凸包
构造一个凸包
二分判断一个点是否在凸包内
求凸包的直径
半平面交
圆
圆与直线的交点
圆与多边形交的面积,使用三角剖分,然后求一个三角形和一个圆的面积。不需要是凸包。
圆与圆的交点
最小圆覆盖
圆的面积并