二维计算几何

/*
暂时跳过内容
复数部分
判断两线段是否相交 (包括是否判断端点) 
求两线段最小距离的平方
*/

#include <bits/stdc++.h>
#define db double
#define ll long long
#define mp make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
const db pi = acos(-1);
const db eps = 1e-6;

比较实数大小

//判断一个实数的符号,在 [-eps,eps]内被认定为 

int sign(db x)
{
	if (x > eps) return 1;
	else if (x < -eps) return -1;
	return 0;
}
// 比较两个实数的大小 
int cmp(db x, db y) { return sign(x - y); }

封装平面上的点及向量

struct Point 
{
	db x, y;
	Point(db x = 0, db y = 0) : x(x), y(y) { }
	//平面点坐标和向量的基本操作 
	//向量 + 向量 or 点 + 向量 
	Point operator+ (const Point& p) const { return Point(x + p.x, y + p.y); }
	//向量相减 or 点 - 点  = 向量 
	Point operator- (const Point& p) const { return Point(x - p.x, y - p.y); }
	//向量数乘/数除 
	Point operator* (db p) const { return Point(x * p, y * p); }
	Point operator/ (db p) const { return Point(x / p, y / p); }
	//判断向量是否平行 or是否是一个点 
	bool operator== (const Point& p) const { return cmp(x, p.x) && cmp(y, p.y); }
	//求极角 : 在极坐标系中,平面上任何一点到极点的连线和极轴的夹角叫做极角。 单位为弧度 rad 
	db polar_angle() { return atan2(y, x); }
	//内积 
	db dot(const Point& p) { return x * p.x + y * p.y; }
	//外积
	db cross(const Point& p) { return x * p.y - y * p.x; } 
	//点到原点的距离 or 向量的模 
	db length() { return sqrt(x * x + y * y); }
	//向量逆时针旋转 rad 度,rad:弧度 且为逆时针旋转的角 
	Point turn(db p){ return Point(x * cos(p) - y * sin(p), x * sin(p) + y * cos(p)); }
    Point turn90(){ return Point(-y, x); }
    
};

平面向量和与点的拓展操作

typedef Point Vector;
//判断向量BC是否在向量AB的逆时针方向 (点C是否在向量AB左边) 
bool ToLeftTest(Point a, Point b, Point c) { return (b - a).cross(c - b) > 0; } 
//两个向量弧度制下的夹角 
db angle (Vector a, Vector b) { return acos(a.dot(b) / a.length() / b.length()); } 
//两向量构成的四边形面积
db area(Point a, Point b, Point c) { return (b - a).cross(c - a); } 
//向量的单位化和法线
Vector format(Vector& a) 
{
	db l = a.length();
	return Vector(a.x / l, a.y / l);
} 
Vector normal(Vector a)
{
	db l = a.length();
	return Vector(-a.y / l, a.x / l);
}
// q点绕着p点逆时针旋转
Point rotate(Point q, Point p, db angle) 
{
	Point v = q - p; 
    db c = cos(angle), s = sin(angle); 
    return Point(p.x + v.x * c - v.y * s, p.y + v.x * s + v.y * c); 
}

封装平面上的直线

struct Line
{
    Vector v;
    Point p;
    Line(Vector v, Point p):v(v), p(p) {}
    Point get_point_in_line(db t)	//返回直线上一点P = v + (p - v)*t
	{
        return v + (p - v)*t;
    }
};

点与直线的相关操作

//点和直线关系 1 在左侧  -1 在右侧 0 在直线上  A, B:直线上一点,C:待判断关系的点
int relation(Point a, Point b, Point c)
{
    int tag = sign((b - a).cross(c - a));
    if(tag < 0) return 1;
    else if(tag > 0) return -1;
    return 0;
}
//计算两直线交点  直线p + tv 和 q + tw 要确保直线有交点 
Point Get_line_intersection(Point p, Vector v, Point q, Vector w)
{
	//if (v.cross(w) == 0) 无交点 
	Vector u = p - q;
	db t = w.cross(u) / w.cross(v);
	return p + v * t;
} 
//点到直线的距离 点p到直线ab的距离 
db Distance_point_to_line(Point p, Point a, Point b)
{
    Vector v1 =b - a, v2 = p - a;
    return fabs(v1.cross(v2) / v1.length());//如果不取绝对值,那么得到的是有向距离
} 
//点到线段的距离  点p到线段ab的距离 
double Distance_point_to_segment(Point p, Point a, Point b)
{
    if(a == b) return (p - a).length();//(如果重合那么就是两个点之间的距离,直接转成向量求距离即可)
    Vector v1 = b - a, v2 = p - a, v3 = p - b;
    if(sign(v1.dot(v2)) < 0) return v2.length();	//A点左边
    if(sign(v1.dot(v3)) > 0) return v3.length();	//B点右边
    return fabs(v1.cross(v2) / v1.length());	//垂线的距离
}
//点到直线的上的投影点 
Point Get_line_projection(Point a, Point b, Point p)
{
	Vector v = b - a;
	return a + v * (v.dot(p - a) / v.dot(v));
} 
//点到直线上的垂足
Point Foot_point(Point p, Point a, Point b)
{
    Vector x = p - a, y = p - b, z = b - a;
    db len1 = x.dot(z) / z.length(), len2 = - 1.0 * y.dot(z) / z.length();
    return a + z * (len1 / (len1 + len2));
}
//点关于一条直线的对称点 
Point Symmetry_PL(Point p, Point a, Point b)
{
	return p + (Foot_point(p, a, b) - p) * 2;
}
//点是否在线段上 
bool On_segment(Point p, Point a, Point b)
{
	return sign((p - a).cross(p - b)) == 0 && sign((p - a).dot(p - b)) < 0;
} 
//判断两条是直线是否平行
bool Parallel(Line a, Line b)
{
	return sign(a.v.cross(b.v)) == 0;
} 
//两直线关系 0 平行 1 重合 2 相交 
int linecrossline(Line a, Line b)
{ 
	db t = a.v.cross(b.v);
	if (sign(t) == 0)
	{
		db s = a.v.cross(a.p - b.p);
		if (sign(s) == 0) return 0;
		return 1;
	}
	return 2;
}
int main()
{
	printf("无内容\n");	
	return 0;	
} 
posted @ 2021-10-07 20:48  circletime  阅读(84)  评论(0)    收藏  举报