您的位置:首页 > Web前端

hdu5130Signal Interference(圆与多边形相交面积模板)

2015-08-16 18:03 441 查看
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>

#define CL(arr, val) memset(arr, val, sizeof(arr))
#define REP(i, n)for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)for((i) = (h); (i) >= (l); --(i))
#define L(x)(x) << 1
#define R(x)(x) << 1 | 1
#define MID(l, r)(l + r) >> 1
#define Min(x, y)x < y ? x : y
#define Max(x, y)x < y ? y : x
#define E(x)(1 << (x))
#define iabs(x) (x) < 0 ? -(x) : (x)
#define OUT(x)printf("%I64d\n", x)
#define lowbit(x)(x)&(-x)
#define Read()freopen("data.in", "r", stdin)
#define Write()freopen("data.out", "w", stdout);

const double eps = 1e-10;
typedef long long LL;
const int inf = ~0u>>2;

using namespace std;

inline double max (double a, double b) { if (a > b) return a; else return b; }
inline double min (double a, double b) { if (a < b) return a; else return b; }
inline int fi (double a)
{
if (a > eps) return 1;
else if (a >= -eps) return 0;
else return -1;
}
class Vector
{
public:
double x, y;
Vector (void) {}
Vector (double x0, double y0) : x(x0), y(y0) {}
double operator * (const Vector& a) const { return x * a.y - y * a.x; }
double operator % (const Vector& a) const { return x * a.x + y * a.y; }
Vector verti (void) const { return Vector(-y, x); }
double length (void) const { return sqrt(x * x + y * y); }
Vector adjust (double len)
{
double ol = len / length();
return Vector(x * ol, y * ol);
}
Vector oppose (void) { return Vector(-x, -y); }
};
class point
{
public:
double x, y;
point (void) {}
point (double x0, double y0) : x(x0), y(y0) {}
Vector operator - (const point& a) const { return Vector(x - a.x, y - a.y); }
point operator + (const Vector& a) const { return point(x + a.x, y + a.y); }
};
class segment
{
public:
point a, b;
segment (void) {}
segment (point a0, point b0) : a(a0), b(b0) {}
point intersect (const segment& s) const
{
Vector v1 = s.a - a, v2 = s.b - a, v3 = s.b - b, v4 = s.a - b;
double s1 = v1 * v2, s2 = v3 * v4;
double se = s1 + s2;
s1 /= se, s2 /= se;
return point(a.x * s2 + b.x * s1, a.y * s2 + b.y * s1);
}
point pverti (const point& p) const
{
Vector t = (b - a).verti();
segment uv(p, p + t);
return intersect(uv);
}
bool on_segment (const point& p) const
{
if (fi(min(a.x, b.x) - p.x) <= 0 && fi(p.x - max(a.x, b.x)) <= 0 &&
fi(min(a.y, b.y) - p.y) <= 0 && fi(p.y - max(a.y, b.y)) <= 0) return true;
else return false;
}
};

double radius;
point polygon[510];

double kuras_area (point a, point b, double cx, double cy)
{
point ori(cx, cy);
int sgn = fi((b - ori) * (a - ori));
double da = (a - ori).length(), db = (b - ori).length();
int ra = fi(da - radius), rb = fi(db - radius);
double angle = acos(((b - ori) % (a - ori)) / (da * db));
segment t(a, b); point h, u; Vector seg;
double ans, dlt, mov, tangle;

if (fi(da) == 0 || fi(db) == 0) return 0;
else if (sgn == 0) return 0;
else if (ra <= 0 && rb <= 0) return fabs((b - ori) * (a - ori)) / 2 * sgn;
else if (ra >= 0 && rb >= 0)
{
h = t.pverti(ori);
dlt = (h - ori).length();
if (!t.on_segment(h) || fi(dlt - radius) >= 0)
return radius * radius * (angle / 2) * sgn;
else
{
ans = radius * radius * (angle / 2);
tangle = acos(dlt / radius);
ans -= radius * radius * tangle;
ans += radius * sin(tangle) * dlt;
return ans * sgn;
}
}
else
{
h = t.pverti(ori);
dlt = (h - ori).length();
seg = b - a;
mov = sqrt(radius * radius - dlt * dlt);
seg = seg.adjust(mov);
if (t.on_segment(h + seg)) u = h + seg;
else u = h + seg.oppose();
if (ra == 1) swap(a, b);
ans = fabs((a - ori) * (u - ori)) / 2;
tangle = acos(((u - ori) % (b - ori)) / ((u - ori).length() * (b - ori).length()));
ans += radius * radius * (tangle / 2);
return ans * sgn;
}
}

const double pi = acos(-1.0);

int main ()
{
//freopen("data.in", "r", stdin);
int n;
double k;
double area, cx, cy;
double x0, y0, x1, y1;
double x,y;
int cas=1;
while(scanf("%d%lf", &n,&k)==2) {
for(int i = 0; i < n; ++i) {///多边形的点
scanf("%lf%lf", &x, &y);
polygon[i] = point(x, y);///记得修改polygon数组的大小,放置越界
}
scanf("%lf%lf",&x0,&y0);
scanf("%lf%lf",&x1,&y1);
double a0,b0,a1,b1;
a0=(2*x0*k*k-2*x1)/(1-k*k);
b0=(x1*x1-x0*x0*k*k)/(1-k*k);
a1=(2*y0*k*k-2*y1)/(1-k*k);
b1=(y1*y1-y0*y0*k*k)/(1-k*k);

cx=-(a0/2);///圆心x 注意正负
cy=-(a1/2);///圆心y
radius=sqrt((a0*a0+a1*a1)/4-b0-b1);///半径
area = 0;
for (int i = 0; i < n; i++)
area += kuras_area(polygon[i], polygon[(i + 1) % n], cx, cy);
printf("Case %d: %.10lf\n",cas,fabs(area));
cas++;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: