计算几何模板(持续更新=。=)

我在算法竞赛从入门到进阶那里看的,通过做题还加了一些函数,觉得不错来看看吧!

#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define N 100005
#define eps 0.00000001//偏差值1e8
#define pi acos(-1.0)//高精度圆周率
const int maxp = 1010;                    //点的数量
int sgn(double x){                        //判断x是否等于0
    if (fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}
int Dcmp(double x, double y){            //比较两个浮点数:0为相等;-1为小于;1为大于
    if (fabs(x - y) < eps)return 0;
    else return x < y ? -1 : 1;
}
//——————————————————平面几何:点和线————————————————————————
struct Point {                                            //定义点及其基本运算
    double x, y;
    Point() {}    
    Point(double x, double y) :x(x), y(y) {}
    Point operator + (Point B) { return Point(x + B.x, y + B.y); }
    Point operator - (Point B) { return Point(x - B.x, y - B.y); }
    Point operator * (Point B) { return Point(x * B.x, y * B.y); } //长度增大k倍
    Point operator / (Point B) { return Point(x / B.x, y / B.y); } //长度缩小k倍
    bool operator ==(Point B) { return sgn(x - B.x) == 0 && sgn(y - B.y) == 0; }
    bool operator <(Point B)                                                    //比较两个点,用于凸包计算
    {
        return sgn(x - B.x) < 0 || (sgn(x - B.x) == 0 && sgn(y - B.y) < 0);
    }
};
typedef Point Vector;                                                        //定义向量
double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }            //点积
double Len(Vector A) { return sqrt(Dot(A, A)); }                            //向量的长度    
double Len2(Vector A) { return Dot(A, A); }                                    //向量长度的平方
//A与B的夹角
double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Len(A) / Len(B)); }
double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }            //叉积
//三角形ABC面积的两倍
double Area2(Point A, Point B, Point C) { return Cross(B - A, C - A); }
//两点的距离,用两种方式实现
double Distance(Point A, Point B) { return hypot(A.x - B.x, A.y - B.y); }
double Dist(Point A, Point B){
    return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}
//向量A的单位法向量
Vector Normal(Vector A) { return Vector(-A.y / Len(A), A.x / Len(A)); }
//向量是否平行或重合
bool Parallel(Vector A, Vector B) { return sgn(Cross(A, B)) == 0; }
Vector Rotate(Vector A, double rad) {                                        //向量A逆时针旋转rad度
    return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}
struct Line {                                                                //线上的两个点
    Point p1, p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p, double angle)
    {
        p1 = p;
        if (sgn(angle - pi / 2) == 0) { p2 = (p1 + Point(0, 1)); }
        else { p2 = (p1 + Point(1, tan(angle))); }
    }
};                                                                            
double mult(Point a, Point b, Point o) {                            /////计算叉乘 ao 和 bo
    return (a.x - o.x) * (b.y - o.y) >= (b.x - o.x) * (a.y - o.y);
}
int Graham(Point p[], int n, Point res[]) {                                    //逆时针排序,构造凸包形状
    int top = 1;
    sort(p, p + n);
    if (n == 0) return 0;
    res[0] = p[0];
    if (n == 1) return 0;
    res[1] = p[1];
    if (n == 2) return 0;
    res[2] = p[2];
    for (int i = 2; i < n; i++) {
        while (top && (mult(p[i], res[top], res[top - 1])))
            top--;
        res[++top] = p[i];
    }
    int len = top;
    res[++top] = p[n - 2];
    for (int i = n - 3; i >= 0; i--) {
        while (top != len && (mult(p[i], res[top], res[top - 1])))
            top--;
        res[++top] = p[i];
    }
    return top;
}
struct Polygon
{
    int n;                                                //多边形的顶点数
    Point p[maxp];                                        //多边形的点
    Line v[maxp];                                        //多边形的边
};
//点和线段的关系:0为点p不在线段v上;1为点p在线段v上
bool Point_on_seg(Point p, Line v)                                            
{
    return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <= 0;
}
//判断点和任意多边形的关系:3为点上;2为边上;1为内部;0为外部
int Point_in_polygon(Point pt, Point* p, int n)
{
    int i;
    for (i = 0; i < n; i++) {
        if (p[i] == pt)return 3;
    }
    for (i = 0; i < n; i++) 
    {
        Line v = Line(p[i],p[(i + 1) % n]);
    if (Point_on_seg(pt, v))return 2;
    }
    int num = 0;
    for (int i = 0; i < n; i++)
    {
        int j = (i + 1)%n;
        int c = sgn(Cross(pt - p[j], p[i] - p[j]));
        int u = sgn(p[i].y - pt.y);
        int v = sgn(p[j].y - pt.y);
        if (c > 0 && u < 0 && v >= 0)num++;
        if (c < 0 && u >= 0 && v < 0)num--;
    }
    return num != 0;
}

猜你喜欢

转载自www.cnblogs.com/ch-hui/p/12631194.html