题意: 给出n个半平面, 求出半平面交和一个矩形的面积交。
检验一发板子.
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define maxn 100005
const double eps = 1e-7;
const double INF = 1e20;
const double pi = acos (-1.0);
int dcmp (double x) {
if (fabs (x) < eps) return 0;
return (x < 0 ? -1 : 1);
}
inline double sqr (double x) {return x*x;}
struct Point {
double x, y;
Point (double _x = 0, double _y = 0):x(_x), y(_y) {}
void input () {scanf ("%lf%lf", &x, &y);}
void output () {printf ("%.2f %.2f\n", x, y);}
bool operator == (const Point &b) const {
return (dcmp (x-b.x) == 0 && dcmp (y-b.y) == 0);
}
bool operator < (const Point &b) const {
return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);
}
Point operator + (const Point &b) const {
return Point (x+b.x, y+b.y);
}
Point operator - (const Point &b) const {
return Point (x-b.x, y-b.y);
}
Point operator * (double a) {
return Point (x*a, y*a);
}
Point operator / (double a) {
return Point (x/a, y/a);
}
double len2 () {
return sqr (x) + sqr (y);
}
double len () {
return sqrt (len2 ());
}
Point change_len (double r) {
double l = len ();
if (dcmp (l) == 0) return *this;
r /= l;
return Point (x*r, y*r);
}
Point rotate_left () {
return Point (-y, x);
}
Point rotate_right () {
return Point (y, -x);
}
Point rotate (Point p, double ang) {
Point v = (*this)-p;
double c = cos (ang), s = sin (ang);
return Point (p.x + v.x*c - v.y*s, p.y + v.x*s + v.y*c);
}
Point normal () {
double l = len ();
return Point (-y/l, x/l);
}
};
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;
}
double dis (Point a, Point b) {
Point p = b-a; return p.len ();
}
double rad_degree (double rad) {
return rad/pi*180;
}
double rad (Point a, Point b) {
return fabs (atan2 (fabs (cross (a, b)), dot (a, b)) );
}
bool parallel (Point a, Point b) {
double p = rad (a, b);
return dcmp (p) == 0 || dcmp (p-pi) == 0;
}
struct Line {
Point s, e;
double k;
Line () {}
Line (Point _s, Point _e) {
s = _s, e = _e;
k = atan2 (e.y - s.y,e.x - s.x);
}
Line (Point p, double ang) {
k = ang;
s = p;
if (dcmp (ang-pi/2) == 0) {
e = s + Point (0, 1);
}
else
e = s + Point (1, tan (ang));
}
void input () {
s.input ();
e.input ();
}
void adjust () {
if (e < s) swap (e, s);
}
double length () {
return dis (s, e);
}
void get_angle () {
k = atan2 (e.y - s.y,e.x - s.x);
}
double angle () {
if (dcmp (k) < 0) k += pi;
if (dcmp (k-pi) == 0) k -= pi;
return k;
}
Point operator &(const Line &b)const {
Point res = s;
double t = (cross (s - b.s, b.s - b.e))/cross (s - e, b.s - b.e);
res.x += (e.x - s.x)*t;
res.y += (e.y - s.y)*t;
return res;
}
};
double polygon_area (Point *p, int n) {
double area = 0;
for (int i = 1; i < n-1; i++) {
area += cross (p[i]-p[0], p[i+1]-p[0]);
}
return area/2;
}
bool HPIcmp (const Line &a, const Line &b) {
if (fabs(a.k - b.k) > eps)
return a.k < b.k;
return cross (a.s - b.s, b.e - b.s) < 0;
}
Line Q[maxn];
void HPI(Line line[], int n, Point res[], int &resn) {
int tot = n;
sort(line,line+n,HPIcmp);
tot = 1;
for(int i = 1;i < n;i++){
if(fabs(line[i].k - line[i-1].k) > eps)
line[tot++] = line[i];
}
int head = 0, tail = 1;
Q[0] = line[0];
Q[1] = line[1];
resn = 0;
for (int i = 2; i < tot; i++) {
if (fabs(cross (Q[tail].e-Q[tail].s, Q[tail-1].e-Q[tail-1].s)) < eps || fabs(cross (Q[head].e-Q[head].s, Q[head+1].e-Q[head+1].s)) < eps)
return;
while(head < tail && (cross ((Q[tail]&Q[tail-1])-line[i].s, line[i].e-line[i].s)) > eps) tail--;
while(head < tail && (cross ((Q[head]&Q[head+1]) - line[i].s, line[i].e-line[i].s)) > eps)
head++;
Q[++tail] = line[i];
}
while(head < tail && (cross ((Q[tail]&Q[tail-1]) - Q[head].s, Q[head].e-Q[head].s)) > eps)
tail--;
while(head < tail && (cross ((Q[head]&Q[head-1]) -Q[tail].s, Q[tail].e-Q[tail].e)) > eps)
head++;
if(tail <= head + 1)
return;
for(int i = head; i < tail; i++)
res[resn++] = Q[i]&Q[i+1];
if(head < tail - 1)
res[resn++] = Q[head]&Q[tail];
}
int n, m;
Point ans[maxn];
Line hp[maxn];
int main () {
while (cin >> n) {
for (int i = 0; i < n; i++) {
hp[i].input ();
hp[i].get_angle ();
}
hp[n++] = Line (Point (0, 0), Point (10000, 0));
hp[n++] = Line (Point (10000, 0), Point (10000, 10000));
hp[n++] = Line (Point (10000, 10000), Point (0, 10000));
hp[n++] = Line (Point (0, 10000), Point (0, 0));
HPI (hp, n, ans, m);
if (m) {
printf ("%.1f\n", polygon_area (ans, m));
}
else
printf ("0.0\n");
}
return 0;
}