poj2540
半平面类的模板。。
用n个半平面去切割一个多边形。。最后求多边形面积。。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
const double EPS = 1e-6;
struct Point
{
Point() {}
Point(double _x, double _y): x(_x), y(_y) {}
void input(){scanf("%lf%lf", &x, &y);}
double getDis(Point &rhs)
{
double xx = x - rhs.x;
xx *= xx;
double yy = y - rhs.y;
yy *= yy;
return sqrt(xx + yy);
}
double x, y;
};
double operator ^(Point lhs, Point rhs){return lhs.x * rhs.y - lhs.y * rhs.x;}
Point operator +(Point lhs, Point rhs){return Point(lhs.x + rhs.x, lhs.y + rhs.y);}
Point operator -(Point lhs, Point rhs){return Point(lhs.x - rhs.x, lhs.y - rhs.y);}
Point operator /(Point lhs, double rhs){return Point(lhs.x / rhs, lhs.y / rhs);}
Point operator *(Point lhs, double rhs){return Point(lhs.x * rhs, lhs.y * rhs);}
bool isCross(Point &a, Point &b, Point &c, Point &d)
{
if(min(a.x, b.x) <= max(c.x, d.x) &&
min(a.y, b.y) <= max(c.y, d.y) &&
min(c.x, d.x) <= max(a.x, b.x) &&
min(c.y, d.y) <= max(a.y, b.y))
{
double u, v, w, z;
u = (c - a) ^ (b - a);
v = (d - a) ^ (b - a);
w = (a - c) ^ (d - c);
z = (b - c) ^ (d - c);
if(u * v <= EPS && w * z <= EPS && fabs((a - b) ^ (c - d)) > EPS) return true;
}
return false;
}
Point getIntersect(Point &a, Point &b, Point &c, Point &d)
{
double D = (a - b) ^ (c - d);
double a1 = b.y - a.y, a2 = d.y - c.y;
double b1 = a.x - b.x, b2 = c.x - d.x;
double c1 = a ^ (b - a), c2 = c ^ (d - c);
Point ret = Point((b2 * c1 - b1 * c2) / D, (a1 * c2 - a2 * c1) / D);
return ret;
}
double getPolygonArea(vector<Point> &point)
{
double ret = 0.0;
int n = point.size();
for(int i = 0; i < n; ++i)
{
int nxt = (i + 1) % n;
ret += point[nxt] ^ point[i];
}
return ret / 2.0;
}
struct HalfPlane
{
double a, b, c;//Ax + By + C = 0
bool isDownSide;//下方半平面 = true(B < 0)
HalfPlane(Point p, Point q, bool _isDownSide)
{
a = p.y - q.y;
b = q.x - p.x;
c = p ^ q;
isDownSide = _isDownSide;
}
HalfPlane() {}
HalfPlane(double _a, double _b, double _c, bool _isDownSide = true):
a(_a), b(_b), c(_c), isDownSide(_isDownSide) {}
double calc(Point &t)
{
return t.x * a + t.y * b + c;
}
Point getIntersect(Point &a, Point &b)//半平面与直线的交点
{
Point ret;
double t1 = calc(a), t2 = calc(b);
ret.x = (t2 * a.x - t1 * b.x) / (t2 - t1);
ret.y = (t2 * a.y - t1 * b.y) / (t2 - t1);
return ret;
}
bool isInHalfPlane(Point &t)//一个点是否在半平面内
{
double temp = calc(t);
if(isDownSide) return temp <= -EPS;
else return temp >= EPS;
}
};
HalfPlane h;
vector<Point> point, out;
Point pre, now;
void getCut(vector<Point> &a, HalfPlane &h, vector<Point> &out)
{
int n = a.size();
out.clear();
for(int i = 0; i < n; ++i)
{
if(h.isInHalfPlane(a[i])) out.push_back(a[i]);
else
{
int pre = (i + n - 1) % n;
if(h.isInHalfPlane(a[pre])) out.push_back(h.getIntersect(a[pre], a[i]));
int nxt = (i + 1) % n;
if(h.isInHalfPlane(a[nxt])) out.push_back(h.getIntersect(a[i], a[nxt]));
}
}
}
void insertHalfPlane(HalfPlane &h, Point &pre, Point &now, bool choosePre)
{
double a = now.y - pre.y, b = pre.x - now.x;
Point mid = (pre + now) / 2;
swap(a, b);
b = -b;
double c = -(a * mid.x + b * mid.y);
h = HalfPlane(a, b, c);
// printf("%lf %lf %lf\n", a, b, c);
double temp;
if(choosePre) temp = h.calc(pre);
else temp = h.calc(now);
if(temp > 0) h.isDownSide = false;
}
int main()
{
// freopen("in.txt", "r", stdin);
double x, y;
char buf[50];
point.push_back(Point(0, 0));
point.push_back(Point(10, 0));
point.push_back(Point(10, 10));
point.push_back(Point(0, 10));
pre = Point(0, 0);
bool empty = false;
while(scanf("%lf%lf%s", &x, &y, buf) != EOF)
{
if(buf[0] == 'S') empty = true;
if(empty)
{
puts("0.00");
continue;
}
now = Point(x, y);
if(buf[0] == 'C')
{
insertHalfPlane(h, pre, now, true);
}
else
{
insertHalfPlane(h, pre, now, false);
}
getCut(point, h, out);
// for(auto i : out)
// {
// printf("%lf %lf\n", i.x, i.y);
// }
point = out;
if(out.size() == 0)
{
empty = true;
}
printf("%.2lf\n", fabs(getPolygonArea(point)));
pre = now;
}
}