An Easy Problem?(poj2826线段相交,直线线段相交)

An Easy Problem?!(poj2826线段相交,直线线段相交)

题意:给你两个同样长的木板,围城一个多边形,水从空中垂直下落,问木板能盛放多少体积的水。

思路:分类讨论

1.如果线段没有交点,那么面积就是0

2.如果线段有交点,但是有一个模板被另一个木板覆盖还是接不到水,怎么判断了,过两个木板的最高的两个点做垂线,如果垂线和和交点到另一木板的顶点这段相交,说明木板有覆盖,不行可以画个图试试,但是覆盖不一定遮挡,所以要判断交点是在另一个木板顶点的上下,在上面说明木板被覆盖,面积为0,反之没有

An Easy Problem?(poj2826线段相交,直线线段相交)

3.因为盛水是水平的,所以过另个木板的顶点做水平线,如果水平线的交点在交点和顶点之间,那么面积就是这三个顶点的面积

An Easy Problem?(poj2826线段相交,直线线段相交)

这题需要直线与线段相交,线段与线段相交,点在线段和点在直线上。

直线与线段相交,只要有一个叉乘小于0即可,但是有可能叉乘等于0,一个点在直线上,还要判断点是否在线段上,用点到直线的距离,距离为0就在,反之就不再

点到直线距离,面积除以底。

直线与线段的交点,求出直线与直线的交点,判断他是否在线段上,判线段上还要注意端点,

线段与线段的交点,也是求出直线与直线的交点 ,判断他是否同时在两个线段上,或者可以先判断两个线段是否相交,然后直接求交点

点在线段上,叉积和点积同时用并且在判断是否在两端点

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct Point
{
    double x,y;
    Point(double x = 0,double y = 0):x(x),y(y){}
};
typedef Point Vector;
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) ;}
Vector operator / (Vector a,double p) { return Vector(a.x/p,a.y/p) ;}
double Dot(Vector a,Vector b) { return a.x*b.x + a.y*b.y ;}
double Length(Vector a) { return sqrt(Dot(a,a)) ;}
double Cross(Vector a, Vector b) { return a.x*b.y - a.y*b.x ;}
const double eps = 1e-8;
int dcmp(double x)
{
    if(fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}
bool operator == (Point a,Point b)
{
    return dcmp(a.x-b.x) == 0&& dcmp(a.y-b.y) == 0;
}
bool operator < (Point a,Point b)
{
    return a.x < b.x || (a.x == b.x && a.y < b.y);
}


bool Onsegment(Point p,Point a,Point b)
{
    return dcmp(Cross(b-a,p-a)) == 0 && dcmp(Dot(b-p,a-p)) < 0 || (p == a) || (p == b);
}

bool OnLine(Point p,Point a,Point b)
{
    return fabs(Cross(p-a,a-b)) / Length(b-a);
}

bool SegmentIntersection(Point a,Point b,Point c,Point d)
{
    double d1 = Cross(b-a,c-a),d2 = Cross(b-a,d-a),d3 = Cross(d-c,a-c),d4 = Cross(d-c,b-c);
    if(dcmp(d1)*dcmp(d2) < 0 || dcmp(d3)*dcmp(d4) < 0) return true;
    else if(dcmp(d1) == 0 && !OnLine(c,a,b) ) return true;
    else if(dcmp(d2) == 0 && !OnLine(d,a,b) ) return true;
    else if(dcmp(d3) == 0 && !OnLine(a,c,d) ) return true;
    else if(dcmp(d4) == 0 && !OnLine(b,c,d) ) return true;
    else return false;
}

bool Segmentsection(Point a,Point b,Point c,Point d)
{
    double d1 = Cross(b-a,c-a),d2 = Cross(b-a,d-a),d3 = Cross(d-c,a-c),d4 = Cross(d-c,b-c);
    if(dcmp(d1)*dcmp(d2) < 0 && dcmp(d3)*dcmp(d4) < 0) return true;
    else if(dcmp(d1) == 0 && Onsegment(c,a,b) ) return true;
    else if(dcmp(d2) == 0 && Onsegment(d,a,b) ) return true;
    else if(dcmp(d3) == 0 && Onsegment(a,c,d) ) return true;
    else if(dcmp(d4) == 0 && Onsegment(b,c,d) ) return true;
    else return false;
}
bool pointInpoly(Point p,Point a,Point b,Point c,Point d)
{
    double d1 = Cross(b-a,p-a);
    double d2 = Cross(d-c,p-c);
    double d3 = Cross(c-b,p-b);
    double d4 = Cross(a-d,p-d);
    return dcmp(d1)*dcmp(d2) > 0 && dcmp(d3)*dcmp(d4) > 0;
}

Point Segment(Point p,Vector v,Point q,Vector w)
{
    Vector u = p-q;
    double t = Cross(w,u) / Cross(v,w);
    return p + v*t;
}
struct Line
{
    Point s,e;
    Line(Point s = 0,Point e = 0) :s(s),e(e){}
};


Point Max(Point a,Point b)
{
    return a.y > b.y ? a : b;
}


int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        Point a,b,c,d;
        scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
        scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y);
        Point P1 = Max(a,b);
        Point P2 = Max(c,d);
        if(!Segmentsection(a,b,c,d)) printf("0.00\n");
        else if(a.y == b.y || c.y == d.y) printf("0.00\n");
        else if(!Cross(b-a,c-d)) printf("0.00\n");
        else
        {
            Point k = Segment(a,b-a,c,d-c);
            Point P3 = Point(P1.x,P1.y+1);
            Point P4 = Point(P2.x,P2.y+1);

            if(SegmentIntersection(P1,P3,c,d))
            {
                Point k1 = Segment(P1,P3-P1,c,d-c);
                if(Onsegment(k1,P2,k))
                {
                    if(dcmp(P1.y-k1.y) <= 0)
                    {
                        printf("0.00\n");continue;
                    }
                }
            }
            if(SegmentIntersection(P2,P4,a,b))
            {
                Point k1 = Segment(P2,P4-P2,a,b-a);
                if(Onsegment(k1,P1,k))
                {
                    if(dcmp(P2.y-k1.y) <= 0)
                    {
                         printf("0.00\n");continue;
                    }
                }
            }

            P3 = Point(P1.x+1,P1.y);
            P4 = Point(P2.x+1,P2.y);
            if(SegmentIntersection(P1,P3,c,d))
            {
                Point k1 = Segment(P1,P3-P1,c,d-c);
                if(Onsegment(k1,P2,k))
                    printf("%.2lf\n",fabs(Cross(P1-k,k1-k))/2);continue;
            }
            if(SegmentIntersection(P2,P4,a,b))
            {
                Point k1 = Segment(P2,P4-P2,a,b-a);
                if(Onsegment(k1,P1,k))
                    printf("%.2lf\n",fabs(Cross(P2-k,k1-k))/2);continue;
            }
        }
    }
    return 0;
}