Polygons
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 174 Accepted Submission(s): 63
Problem Description
Given two convex polygons, they may or may not overlap. If they do overlap, they will do so to differing degrees and in different ways. Write a program that will read in the coordinates of the corners of two convex polygons and calculate the `exclusive or' of the two areas, that is the area that is bounded by exactly one of the polygons. The desired area is shaded in the following diagram:
![](https://i-blog.csdnimg.cn/blog_migrate/16babf7f0ef44bb39d05c45e1be5d990.gif)
Input
Input will consist of pairs of lines each containing the number of vertices of the polygon, followed by that many pairs of integers representing the x,y coordinates of the corners in a clockwise direction. All the coordinates will be positive integers less than 100. For each pair of polygons (pair of lines in the data file), your program should print out the desired area correct to two decimal places. The input will end with a line containing a zero (0).
Output
Output will consist of a single line containing the desired area written as a succession of eight (8) digit fields with two (2) digits after the decimal point. There will not be enough cases to need more than one line.
Sample Input
3 5 5 8 1 2 3 3 5 5 8 1 2 3 4 1 2 1 4 5 4 5 2 6 6 3 8 2 8 1 4 1 4 2 5 3 0
Sample Output
0.00 13.50
Source
用其中一个构造线去切割另一个
最后切割出来的多边形就是覆盖区域
/*
* @Author: Sky-J
* @Date: 2014-09-10 16:30:29
* @Last Modified by: Sky-J
* @Last Modified time: 2014-09-10 19:40:46
*/
#define DeBUG
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <string>
#include <set>
#include <sstream>
#include <map>
#include <list>
#include <bitset>
using namespace std ;
#define zero {0}
#define INF 0x3f3f3f3f
#define EPS 1e-6
#define TRUE true
#define FALSE false
typedef long long LL;
const double PI = acos(-1.0);
//#pragma comment(linker, "/STACK:102400000,102400000")
inline int sgn(double x)
{
return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);
}
#define N 100005
// Point class
struct Point;
typedef Point Vec;
struct Point
{
double x, y;
Point () {}
Point(double a, double b)
{
x = a;
y = b;
}
};
Vec operator + (const Vec &a, const Vec &b) //点加法
{
return Vec(a.x + b.x, a.y + b.y);
}
Vec operator - (const Vec &a, const Vec &b) //点减法
{
return Vec(a.x - b.x, a.y - b.y);
}
Vec operator * (const Vec &a, const double &p) //点与常数相乘
{
return Vec(a.x * p, a.y * p);
}
bool operator == (const Vec &a, const Point &b) //点相等判断
{
return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;
}
inline double dotDet(Vec a, Vec b)//点乘
{
return a.x * b.x + a.y * b.y;
}
inline double crossDet(Vec a, Vec b)//叉乘
{
return a.x * b.y - a.y * b.x;
}
inline double crossDet(Point o, Point a, Point b)//向量叉乘
{
return crossDet(a - o, b - o);
}
inline bool onSeg(Point x, Point a, Point b)//判断点在线段ab上,加上||x==a||x==b在端点也算
{
return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0 || x == a || x == b;
}
Point lineIntersect(Point P, Vec v, Point Q, Vec w)//直线相交返回交点
{
Vec u = P - Q;
double t = crossDet(w, u) / crossDet(v, w);//t必须为1/2的,可为什么要这么写呢?
return P + v * t;
}
// Polygon class
struct Poly//平面类
{
vector<Point> pt;//保存平面对应的端点
Poly()
{
pt.clear();
}
~Poly() {}
Poly(vector<Point> pt0): pt(pt0) {} //使用vector进行初始化
Point operator [](int x) const//重载[]返回对应端点
{
return pt[x];
}
int size()//返回对应平面点数
{
return pt.size();
}
double area()//得到面积,凹凸多边形均可
{
double ret = 0.0;
int sz = pt.size();
for (int i = 0; i < sz; i++)
{
int j = (i + 1) % sz;
ret += crossDet(pt[i], pt[j]);
}
return ret / 2.0;
}
void output()
{
printf("%d\n", pt.size());
for (int i = 0; i < pt.size(); i++)
{
printf("%lf %lf\n", pt[i].x, pt[i].y);
}
}
};
Poly cutPoly(Poly &poly, Point a, Point b)
{
Poly ret = Poly();
int n = poly.size();
for (int i = 0; i < n; i++)
{
Point c = poly[i], d = poly[(i + 1) % n];
if (sgn(crossDet(b - a, c - a)) >= 0)
ret.pt.push_back(c);
if (sgn(crossDet(b - a, c - d)) != 0)
{
Point ip = lineIntersect(a, b - a, c, d - c);
if (onSeg(ip, c, d)) ret.pt.push_back(ip);
}
}
return ret;
}
int main()
{
#ifdef DeBUGs
freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);
#endif
int n1, n2;
while (scanf("%d", &n1), n1)
{
Poly poly1, poly2;
Point p;
for (int i = 0; i < n1; i++)
{
scanf("%lf%lf", &p.x, &p.y);
poly1.pt.push_back(p);
}
scanf("%d", &n2);
for (int i = 0; i < n2; i++)
{
scanf("%lf%lf", &p.x, &p.y);
poly2.pt.push_back(p);
}
double ret = poly1.area();
if (sgn(ret) < 0)//通过计算多边形面积正负判断给出点的方向,逆时针为正
{
reverse(poly1.pt.begin(), poly1.pt.end());//点逆序
ret = fabs(ret);
}
double area = poly2.area();
if (sgn(area) < 0)
{
reverse(poly2.pt.begin(), poly2.pt.end());
area = fabs(area);
}
poly2.pt.push_back(poly2.pt[0]);
ret += area;
Poly ans = poly1;
for (int i = 0; i < n2; i++)
{
ans = cutPoly(ans, poly2[i], poly2[i + 1]);
}
// ans.output();
printf("%8.2lf", ret - 2 * ans.area());
}
puts("");
return 0;
}