La_Pluma 的 数学
一百行的几何板子?
#include <cmath>
#include <cstdio>
#include <algorithm>
namespace La_Pluma_math{
const double eps = 1e-10;
typedef double Point_type;
struct Point; struct Vec; struct Line; struct Segment;
double check_0(double); // 判丢精的 0
double dis(const Point, const Point); // 点到点的距离
double dis(const Point, const Line); // 点到直线距离
double dis(const Line, const Point); // 直线到点距离
double dis(const Point, const Segment); // 点到线段距离
double dis(const Segment, const Point); // 线段到点距离
struct Point{ // 点
Point_type x, y;
Point():x(), y(){} // 默认构造函数
Point(const Vec); // 用向量初始化 (感觉非常SB)
Point(Point_type, Point_type); // 用坐标初始化
bool operator == (const Point); // 判断是否为同一个点
bool operator != (const Point); // 判断是否不为同一个点
};
struct Vec{ // 向量
double x, y;
Vec():x(), y(){} // 默认构造函数
Vec(const Point); // 用点初始化
Vec(const Segment); // 用线段初始化
Vec(double, double); // 用坐标初始化
Vec(const Point, const Point); // 用两个点初始化 (起点和终点)
Vec(double, double, double, double); // 用两个坐标初始化 (起点和终点)
Vec operator + (const Vec); // 向量加
Vec operator - (const Vec); // 向量减
double operator ^ (const Vec); // 向量叉积的模
double operator * (const Vec); // 向量点积
double operator ~ (); // 向量的模
Vec operator += (const Vec); // 以下处理一些奇怪的运算符
Vec operator -= (const Vec); // 结果发现也就这些
Vec operator - (); // 又有谁能想到减号也可以是单目运算符呢
bool operator == (const Vec); // 判断是否为共线向量
bool operator != (const Vec); // 判断是否不为共线向量
};
struct Line{ // 直线
double A, B, C;
Line():A(), B(), C(){} // 默认构造函数
Line(const Segment); // 用线段初始化
Line(double, double); // 用斜截式初始化
Line(const Point, const Point); // 用两个点初始化
Line(double, double, double, double); // 用两个坐标初始化
Point operator ^ (const Line); // 求直线的交点
bool operator == (const Line); // 判断是否为同一条直线
bool operator != (const Line); // 判断是否不为同一条直线
double operator [] (const double); // 求 x 对应的 y 值
};
struct Segment{ // 线段
Point a, b;
Segment():a(),b(){} // 默认构造函数
Segment(const Point, const Point); // 用两个端点初始化
Segment(Point_type, Point_type, Point_type, Point_type); // 用两个坐标初始化
double operator ~ (); // 线段的长度
bool operator < (Segment); // 万能的小于号
bool operator > (Segment); // 进行
bool operator <= (Segment); // 一个
bool operator >= (Segment); // 重的载
bool operator == (Segment); // 判断线段的长度是否相等
bool operator != (Segment); // 判断线段的长度是否不相等
};
Point::Point(const Vec a) { x = a.x, y = a.y; }
Point::Point(Point_type x, Point_type y) { this->x = x, this->y = y; }
bool Point::operator == (const Point a) { return x == a.x && y == a.y; }
bool Point::operator != (const Point a) { return !(*this == a); }
Vec::Vec(const Point a) { x = a.x, y = a.y; }
Vec::Vec(const Segment a) { *this = Vec(a.a, a.b); }
Vec::Vec(const Point a, const Point b) { *this = Vec(b) - Vec(a); }
Vec::Vec(double x, double y) { this->x = x, this->y = y; }
Vec Vec::operator + (const Vec b) { return Vec(x + b.x, y + b.y); }
Vec Vec::operator - (const Vec b) { return Vec(x - b.x, y - b.y); }
Vec Vec::operator - () { return Vec(-x , -y ); }
double Vec::operator ^ (const Vec b) { return x * b.y - b.x * y; }
double Vec::operator * (const Vec b) { return x * b.x + y * b.y; }
double Vec::operator ~ () { return sqrt(x * x + y * y); }
Vec Vec::operator += (const Vec b) { return *this = *this + b; }
Vec Vec::operator -= (const Vec b) { return *this = *this - b; }
bool Vec::operator == (const Vec b) { if(!check_0(b.x)) return !check_0(x); if(!check_0(b.y)) return !check_0(y); return check_0(y / b.y - x / b.x) == 0; }
bool Vec::operator != (const Vec b) { return !(*this == b); }
Line::Line(const Segment a) { *this = Line(a.a, a.b); }
Line::Line(double k, double b) { A = k, B = 0, C = b; }
Line::Line(double a, double b, double c, double d) { *this = Line(Point(a, b), Point(c, d)); }
Line::Line(const Point a, const Point b){
if(a.x == b.x) A = 1, B = 0, C = -a.x;
else if(a.y == b.y) A = 0, B = 1, C = -a.y;
else A = (double)(a.y - b.y) / (a.x - b.x), B = -1, C = (double)(a.x * b.y - b.x * a.y) / (a.x - b.x);
}
Point Line::operator ^ (const Line a) { return Point((B * a.C - a.B * C) / (A * a.B - a.A * B), -(A * a.C - a.A * C) / (A * a.B - a.A * B)); }
bool Line::operator == (const Line a) { return check_0(A * a.B - B * a.A) == 0 && check_0(A * a.C - C * a.A) == 0 && check_0(B * a.C - C * a.B) == 0; }
bool Line::operator != (const Line a) { return !(*this == a); }
double Line::operator [] (const double a) { return -(C + A * a) / B; }
Segment::Segment(const Point a, const Point b) { this->a = a, this->b = b; }
Segment::Segment(Point_type a, Point_type b, Point_type c, Point_type d) { *this = Segment(Point(a, b), Point(c, d)); }// 因为一些显然的问题, 这里就不对齐了
double Segment::operator ~ () { return dis(a, b); }
bool Segment::operator < (Segment a) { return (~(*this)) < (~a); }
bool Segment::operator > (Segment a) { return a < *this; }
bool Segment::operator <= (Segment a) { return !(*this > a); }
bool Segment::operator >= (Segment a) { return !(*this < a); }
bool Segment::operator == (Segment a) { return !(*this < a) && !(*this > a); }
bool Segment::operator != (Segment a) { return (*this < a) || (*this > a); }
double check_0(double a) { return fabs(a) < eps ? 0 : a; }
double dis(const Point pos1, const Point pos2) { return check_0(sqrt((pos1.x - pos2.x) * (pos1.x - pos2.x) + (pos1.y - pos2.y) * (pos1.y - pos2.y))); }
double dis(const Line link, const Point pos) { return check_0(fabs(link.A * pos.x + link.B * pos.y + link.C) / sqrt(link.A * link.A + link.B * link.B)); }
double dis(const Point pos, const Line link) { return dis(link, pos); }
double dis(const Point pos, const Segment Seg) { return dis(Seg, pos); }
double dis(const Segment Seg, const Point pos) {
Vec vector1(Seg.a, pos);
Vec vector2(Seg.b, pos);
Vec vector3 = Seg;
if(check_0(vector1 * vector3) < 0) return ~vector1;
if(check_0(vector2 * vector3) > 0) return ~vector2;
return check_0(fabs((vector1 ^ vector3) / (~vector3)));
}
}
using namespace La_Pluma_math;
int main(){
int T; scanf("%d", &T);
while(T--){
int a, b, c, d, e, f, g, h;
scanf("%d%d%d%d%d%d%d%d", &a, &b, &c, &d, &e, &f, &g, &h);
Segment n(a, b, c, d), m(e, f, g, h);
if(b > d) std::swap(n.a, n.b); if(f > h) std::swap(m.a, m.b);
if(Vec(n) == Vec(m) || Vec(n) == Vec(1, 0) || Vec(m) == Vec(1, 0)) {puts("0.00"); continue;}
Point pos = Line(n) ^ Line(m);
if(dis(pos, n) || dis(pos, m)) {puts("0.00"); continue;}
if(Line(n).B * Line(n).A * Line(m).B * Line(m).A > 0){
if(n.b.y >= m.b.y && !dis(Point(m.b.x, Line(n)[m.b.x]), n) && check_0(Line(n)[m.b.x] - m.b.y) >= 0) {puts("0.00"); continue;}
if(n.b.y <= m.b.y && !dis(Point(n.b.x, Line(m)[n.b.x]), m) && check_0(Line(m)[n.b.x] - n.b.y) >= 0) {puts("0.00"); continue;}
}
if(n.b.y < m.b.y) m.b = Point(-(Line(m).C + Line(m).B * n.b.y) / Line(m).A, n.b.y);
else n.b = Point(-(Line(n).C + Line(n).B * m.b.y) / Line(n).A, m.b.y);
printf("%.2f\n", fabs(Vec(pos, n.b) ^ Vec(pos, m.b)) * 0.5 + eps);
}
}
有些事情必须声明一下, 可以保证过编译, 不保证不出错