天天看点

POJ 2826 (计算几何)

堆坂子的题目。

判断线段相交,共线视为不相交。

求出交点,然后判断在上面的那条线段有没有覆盖住下面的那条线段。

最后输出面积的时候小心输出-0.00的情况。

#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef unsigned long long ll;
#define maxn 111111
#define pi acos (-1)
#define rotate Rotate

const double eps = 1e-8;
int dcmp (double x) {
    if (fabs (x) < eps)
        return 0;
    else return x < 0 ? -1 : 1;
}
struct point {
    double x, y;
    point (double _x = 0, double _y = 0) : x(_x), y(_y) {}
    point operator - (point a) const {
        return point (x-a.x, y-a.y);
    }
    point operator + (point a) const {
        return point (x+a.x, y+a.y);
    }
    bool operator < (const point &a) const {
        return x < a.x || (x == a.x && y < a.y);
    }
    bool operator == (const point &a) const {
        return dcmp (x-a.x) == 0 && dcmp (y-a.y) == 0;
    }
}p[maxn];

point operator * (point a, double p) {
    return point (a.x*p, a.y*p);
}
double cross (point a, point b) {
    return a.x*b.y-a.y*b.x;
}
double dot (point a, point b) {
    return a.x*b.x + a.y*b.y;
}

bool OnSegment (point p, point a1, point a2) {
    return dcmp (cross (a1-p, a2-p) == 0) && dcmp (dot (a1-p, a2-p) <= 0);
}

bool SegmentProperIntersection (point a1, point a2, point b1, point b2) {
    double c1 = cross (a2-a1, b1-a1), c2 = cross (a2-a1, b2-a1),
        c3 = cross (b2-b1, a1-b1), c4 = cross (b2-b1, a2-b1);
    if (dcmp (c1) == 0 && dcmp (c2) == 0)
        return 0; //两条线段共线
    if (dcmp (c1)*dcmp (c2) < 0 && dcmp (c3)*dcmp (c4) < 0)
        return 1;
    else if (OnSegment (a1, b1, b2) || OnSegment (a2, b1, b2) || OnSegment (b1, a1, a2) || OnSegment (b2, a1, a2)) {
        return 1;
    }
    return 0;
}

point GetLineIntersection (point p, point v, point q, point w) {
    point u = p-q;
    double t = cross (w, u) / cross (v, w);
    return p+v*t;
}

int n, m, tot;

bool ok (point a1, point a2) {
    if (a1.x*a2.x <= 0)
        return 1;
    double ang1 = abs (a1.y/a1.x), ang2 = abs (a2.y/a2.x);
    if (ang1 > ang2 && fabs (a1.x) >= fabs (a2.x))
        return 0;
    if (ang2 > ang1 && fabs (a2.x) >= fabs (a1.x))
        return 0;
    return 1;
}

const double INF = 1e30;
int main () {
    //freopen ("in", "r", stdin);
    int t;
    scanf ("%d", &t);
    point a1, a2, b1, b2;
    while (t--) {
        cin >> a1.x >> a1.y >> a2.x >> a2.y;
        cin >> b1.x >> b1.y >> b2.x >> b2.y;
        if (a1.y > a2.y)
            swap (a1, a2);
        if (b1.y > b2.y)
            swap (b1, b2);
        if (!SegmentProperIntersection (a1, a2, b1, b2)) {
            printf ("0.00\n");
        }
        else {
            point ans = GetLineIntersection (a1, a2-a1, b1, b2-b1);
            double h = min (a2.y, b2.y);
            if (dcmp (h-ans.y) == 0 || !ok (a2-ans, b2-ans)) {
                printf ("0.00\n");
                continue;
            }
            double p2 = b1.x+(b2.x-b1.x)*(h-b1.y)/(b2.y-b1.y);
            double p1 = a1.x+(a2.x-a1.x)*(h-a1.y)/(a2.y-a1.y);
            double area = (p2-p1)*(h-ans.y)/2;
            printf ("%.2f\n", abs (area)+eps);
        }
    }
    return 0;
}
           

继续阅读