题意:给你两个线段 填空垂直下雨 问能接到的水的面积
ans = 0.0:
1.存在线段平行y轴
2.两线段重合平行不相交
2.一条线挡住另一条
求S:点到直线的距离 * x / 2
注:自己加的点虚构的坐标可能和原有的点撞上啊!加个一啊!
答案最好加eps
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
struct Point{
double x,y;
Point(double x = 0,double y = 0) : x(x),y(y) {}
}A1,A2,B1,B2;
typedef Point Vector;
struct NODE{
Point p,q;
}a[1005];
int t;
int dcmp(double x){//equal ?= 0
if(fabs(x) < eps) return 0;
else return x < 0 ? -1:1;
}
//运算符重载
Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y); }
Vector operator - (Vector A, Vector B){ return Vector(A.x-B.x, A.y-B.y); }
Vector operator * (Vector A, double p){ return Vector(A.x*p, A.y*p); }
bool operator == (const Point &a, const Point &b){
return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y; }
double Cross(Vector A, Vector B){ return A.x*B.y - A.y*B.x; }
bool Collinear(Point P1,Point P2,Point P3,Point P4){
double A = Cross(P1 - P2,P3 - P2);
double B = Cross(P1 - P2,P4 - P2);
if(!dcmp(A) && !dcmp(B)) return 1;
return 0;
}
//判断平行
bool Parallel(Point P1,Point P2,Point P3,Point P4){
if(dcmp(Cross(P1 - P2,P3 - P4)) == 0) return 1;
return 0;
}
//P点再P1P2上 叉积==0
bool OnSeg(Point P,Point P1,Point P2){
return dcmp(Cross(P1 - P,P2 - P)) == 0 && dcmp(Dot(P1 - P,P2 - P)) <= 0;
}
//?相交
bool check(Point P1,Point P2,Point P3,Point P4){//原线段&线段 注直线&线段
//端点在线上 非规范相交
if(OnSeg(P1,P3,P4)) return 1;
if(OnSeg(P2,P3,P4)) return 1;
if(OnSeg(P3,P1,P2)) return 1;
if(OnSeg(P4,P1,P2)) return 1;
//跨立实验规范相交
double _A = Cross(P1 - P2,P3 - P2);
double _B = Cross(P1 - P2,P4 - P2);
double _C = Cross(P3 - P4,P1 - P4);
double _D = Cross(P3 - P4,P2 - P4);
return dcmp(_A) * dcmp(_B) < 0 && dcmp(_C) * dcmp(_D) < 0;//=0重合或平行
}
//一般法求交点
Point Ist(Point P1,Point P2,Point P3,Point P4){
Point ist;
ist.x = inf * 1.0;
ist.y = inf * 1.0;
double a1 = 1.0 *(P1.y - P2.y);
double b1 = 1.0 *(P2.x - P1.x);
double c1 = 1.0 *(P1.x * P2.y - P2.x * P1.y);
double a2 = 1.0 *(P3.y - P4.y);
double b2 = 1.0 *(P4.x - P3.x);
double c2 = 1.0 *(P3.x * P4.y - P4.x * P3.y);
double pd = a2 * b1 - a1 * b2;
if(dcmp(pd) == 0) return ist;//无解
ist.x = (c1 * b2 - c2 * b1) / pd;
ist.y = (a2 * c1 - a1 * c2) / (-1.0 * pd);
return ist;
}
//两参数方程求交点,(点,向量,点,向量)
Point Getlinenode(Point P,Point v,Point Q,Point w){
//线1(P1,P2) 线2(P3,P4) (P1,P1-P2,P3,P3-P4)
Point u = P - Q;
double t = Cross(w,u) / Cross(v,w);
return P + v * t;
}
double Length(Vector A){return sqrt(Dot(A,A));}//计算向量的长度
double DistanceToSegment(Point P,Point A,Point B){
if(A==B)return Length(P-A);
Vector v1=B-A,v2=P-A,v3=P-B;
// if(dcmp(Dot(v1,v2))<0)return Length(v2); //第二类第一小类 PA
// else if(dcmp(Dot(v1,v3))>0)return Length(v3);//第二类第二小类 PB
return fabs(Cross(v1,v2))/Length(v1);//垂线长度
}
int main()
{
scanf("%d",&t);
while(t--){
scanf("%lf %lf %lf %lf",&A1.x,&A1.y,&A2.x,&A2.y);
scanf("%lf %lf %lf %lf",&B1.x,&B1.y,&B2.x,&B2.y);
if(Collinear(A1,A2,B1,B2) || Parallel(A1,A2,B1,B2) || A1.y == A2.y || B1.y == B2.y || !check(A1,A2,B1,B2)){//两条线平行重合 || 线垂直 || 两线段不相交
printf("0.00\n");
continue;
}
if(A1.y < A2.y) swap(A1,A2);
if(B1.y < B2.y) swap(B1,B2);
if(A1.y < B1.y){
swap(A1,B1);
swap(A2,B2);
}//1 > 2 A > B
Point O = Ist(A1,A2,B1,B2);
Point C;
C.x = B1.x;
C.y = A1.y;
//B1C - A1A2 B1C垂直x轴
Point F = Ist(B1,C,A1,A2);
// cout << F.x << "#" << F.y << endl;
// cout << A1.y << "@" << B1.y << endl;
if(F.y <= A1.y && F.y >= B1.y){
printf("0.00\n");
continue;
}
Point AB;
AB.y = B1.y;
AB.x = B1.x + 1;
// cout << AB.x << "$" << AB.y << endl;
Point AA1 = Ist(AB,B1,A1,A2);//AA1-B1 O
double h = DistanceToSegment(O,AA1,B1);
printf("%.2f\n",h * fabs(B1.x - AA1.x) / 2 + eps);
}
}