题目链接:[CSU 1812 三角形和矩形]
题意描述:求三角形和矩形相交面积。已知矩形的四条边和三角形的两条边是与坐标轴平行的。
解题思路:真的是一个裸的模版题。首先,求出三角形的在矩形区域的顶点,矩形在三角形区域的顶点。然后求出所有的交点。这些点构成一个凸包,求凸包面积就OK了。
计算几何太不熟练了,导致这个题目省赛的时候没有时间写出来…
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 20;
const long double eps = 1e-8;
long double X1, X2, X3, X4, Y1, Y2, Y3, Y4, ans;
int sgn(long double x) {
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
else return 1;
}
struct Point {
long double x, y;
Point() {}
Point(long double _x, long double _y) {
x = _x;
y = _y;
}
Point operator -(const Point &b)const {
return Point(x - b.x, y - b.y);
}
long double operator ^(const Point &b)const {
return x * b.y - y * b.x;
}
long double operator *(const Point &b)const {
return x * b.x + y * b.y;
}
bool operator ==(const Point& b)const {
return x == b.x && y == b.y;
}
};
struct Line {
Point s, e;
Line() {}
Line(Point _s, Point _e) {
s = _s;
e = _e;
}
pair<int, Point> operator &(const Line &b)const {
Point res = s;
if(sgn((s - e) ^ (b.s - b.e)) == 0) {
if(sgn((s - b.e) ^ (b.s - b.e)) == 0)
return make_pair(0, res); //重合
else return make_pair(1, res); //平行
}
long double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return make_pair(2, res);
}
};
Point plist[MAXN];
int sz;
long double dist(Point a, Point b) {
return sqrt((a - b) * (a - b));
}
bool _cmp(Point p1, Point p2) {
long double tmp = (p1 - plist[0]) ^ (p2 - plist[0]);
if(sgn(tmp) > 0)return true;
else if(sgn(tmp) == 0 && sgn(dist(p1, plist[0]) - dist(p2, plist[0])) <= 0)
return true;
else return false;
}
long double CalcArea(Point p[], int n) {
long double res = 0;
for(int i = 0; i < n; i++)
res += (p[i] ^ p[(i + 1) % n]);
return fabs(res / 2);
}
inline bool inRect(Point p) {
return sgn(p.x - X3) >= 0 && sgn(p.x - X4) <= 0 && sgn(p.y - Y3) >= 0 && sgn(p.y - Y4) <= 0;
}
inline bool inTrig(Point p) {
Point a(X1, Y1), b(X1, Y2), c(X2, Y1);
long double s = fabs((a - b) ^ (a - c));
long double s1 = fabs((p - a) ^ (p - b));
long double s2 = fabs((p - a) ^ (p - c));
long double s3 = fabs((p - b) ^ (p - c));
if(sgn(s1 + s2 + s3 - s) < 0) while(1);
return sgn(s1 + s2 + s3 - s) == 0;
}
int main() {
freopen("input.txt", "r", stdin);
while(cin >> X1 >> Y1 >> X2 >> Y2 >> X3 >> Y3 >> X4 >> Y4) {
Point trig[3] = {Point(X1, Y1), Point(X1, Y2), Point(X2, Y1)};
Point rect[4] = {Point(X3, Y3), Point(X3, Y4), Point(X4, Y4), Point(X4, Y3)};
sz = 0;
for(int i = 0; i < 3; i++) {
if(inRect(trig[i])) {
plist[sz ++] = trig[i];
}
}
for(int i = 0; i < 4; i++) {
if(inTrig(rect[i])) {
plist[sz ++] = rect[i];
}
}
Line L1, L2;
pair<int, Point> ret;
for(int i = 0; i < 3; i++) {
L1 = Line(trig[i], trig[(i + 1) % 3]);
for(int j = 0; j < 4; j++) {
L2 = Line(rect[j], rect[(j + 1) % 4]);
ret = L1 & L2;
if(ret.first == 2) {
Point &t = ret.second;
if(sgn((t.x - trig[i].x) * (t.x - trig[(i + 1) % 3].x)) <= 0 &&
sgn((t.y - trig[i].y) * (t.y - trig[(i + 1) % 3].y)) <= 0 &&
sgn((t.x - rect[j].x) * (t.x - rect[(j + 1) % 4].x)) <= 0 &&
sgn((t.y - rect[j].y) * (t.y - rect[(j + 1) % 4].y)) <= 0)
plist[sz ++] = t;
}
}
}
sort(plist, plist + sz, _cmp);
sz = unique(plist, plist + sz) - plist;
ans = CalcArea(plist, sz);
cout << fixed << setprecision(8) << ans << endl;
}
return 0;
}