/*
暂时跳过内容
复数部分
判断两线段是否相交 (包括是否判断端点)
求两线段最小距离的平方
*/
#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;
}