# 模板（计算几何）

20 篇文章 0 订阅

## 几何

#define F double
F eps=1e-9;
const F pi=acos(-1);

struct point{
F x,y;
point(){}
point(F x,F y):x(x),y(y){}
};
typedef point Vector;
typedef point Point;
Vector operator + (Vector a, Vector b){//向量加法
return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b){//向量减法
return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, F p){//向量数乘
return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, F p){//向量数除
return Vector(a.x / p, a.y / p);
}
int dcmp(F x){//精度三态函数(>0,<0,=0)
if (fabs(x) < eps)return 0;
else if (x > 0)return 1;
return -1;
}
bool operator == (const Point &a, const Point &b){//向量相等
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
F Dot(Vector a, Vector b){//内积
return a.x*b.x + a.y*b.y;
}
F Length(Vector a){//模
return sqrt(Dot(a, a));
}
F Cross(Vector a, Vector b){//外积
return a.x*b.y - a.y*b.x;
}
F Angle(Vector a, Vector b)
{ //夹角,弧度制
F d2 = Dot(a, b) / Length(a) / Length(b);
if (d2 < -1)
d2 = -1;
if (d2 > 1)
d2 = 1;
F ang = acos(d2);
if (Cross(a, b) < 0)
{
ang = -ang;
}
return ang;
}
}
Vector RotateTogether(Vector A1, Vector A2, Vector C){ //A1旋转到A2后，C应该旋转到哪里
F ang = Angle(A1, A2);
return Rotate(C, ang);
}
F Distance(Point a, Point b){//两点间距离
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
F Area(Point a, Point b, Point c){//三角形面积
return fabs(Cross(b - a, c - a) / 2);
}
bool Intersect(Point a, Point b, Point c, Point d){//线段相交（不包括端点）
F t1 = Cross(c - a, d - a)*Cross(c - b, d - b);
F t2 = Cross(a - c, b - c)*Cross(a - d, b - d);
return dcmp(t1) < 0 && dcmp(t2) < 0;
}
bool StrictIntersect(Point a, Point b, Point c, Point d){ //线段相交（包括端点）
return
dcmp(max(a.x, b.x) - min(c.x, d.x)) >= 0
&& dcmp(max(c.x, d.x) - min(a.x, b.x)) >= 0
&& dcmp(max(a.y, b.y) - min(c.y, d.y)) >= 0
&& dcmp(max(c.y, d.y) - min(a.y, b.y)) >= 0
&& dcmp(Cross(c - a, d - a)*Cross(c - b, d - b)) <= 0
&& dcmp(Cross(a - c, b - c)*Cross(a - d, b - d)) <= 0;
}
F DistanceToLine(Point A, Point M, Point N){//点A到直线MN的距离,Error:MN=0
return fabs(Cross(A - M, A - N) / Distance(M, N));
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){//两直线的交点
Vector u = P - Q;
F t = Cross(w, u) / Cross(v, w);
return P + v * t;
}

//求多边形面积（叉积和计算法）
/*模板说明：P[]为多边形的所有顶点，下标为0~n-1，n为多边形边数*/
/*
Point P[1005];
int n;
F PolygonArea(){
F sum = 0;
Point O = Point(0, 0);
for (int i = 0; i < n; i++)
sum += Cross(P[i] - O, P[(i + 1) % n] - O);
if (sum < 0)sum = -sum;
return sum / 2;
}
*/

//求凸包
/*
point p[200009],ans[200009];
int n,top;
point Tmp;//选好的起点
bool cmp(point a,point b){
F ans=Cross(a-Tmp,b-Tmp);
if(dcmp(ans)==0)return dcmp(Distance(a,Tmp)-Distance(b,Tmp))<0;
return ans>0;//表示a到b是逆时针转
}
void Graham(point p[],int n,point ans[],int &top){// 包含共线点
for(int i=2;i<=n;i++){
if(p[i].y<p[1].y||(dcmp(p[i].y-p[1].y)==0&&p[i].x<p[1].x))
swap(p[1],p[i]);
}
Tmp=p[1];
sort(p+2,p+1+n,cmp);
ans[1]=p[1],ans[2]=p[2],top=2;
for(int i=3;i<=n;i++){
while(Cross(ans[top]-ans[top-1],p[i]-ans[top])<0)top--;
ans[++top]=p[i];
}
//最后几个点如果是和p[1]在同一直线上的，那么会漏掉除最远的点以外的点
for(int i=n-1;;i--){
if(Cross(ans[top]-ans[1],p[i]-ans[1])!=0)break;
ans[++top]=p[i];
}
}
void Graham(point p[],int n,point ans[],int &top){// 去掉共线点
if(n<3)return;
for(int i=2;i<=n;i++){
if(p[i].y<p[1].y||(dcmp(p[i].y-p[1].y)==0&&p[i].x<p[1].x))
swap(p[1],p[i]);
}
Tmp=p[1];
sort(p+2,p+1+n,cmp);
ans[1]=p[1],ans[2]=p[2],top=2;
for(int i=3;i<=n;i++){
while(top>2&&dcmp(Cross(ans[top]-ans[top-1],p[i]-ans[top]))<=0)top--;
ans[++top]=p[i];
if(top>2&&dcmp(Cross(ans[top]-ans[top-1],ans[top-1]-ans[top-2]))==0)ans[top-1]=ans[top],--top;
}
}
*/

struct Circle{
Point c;
F r;
Point gpoint(F a){//基于圆心角求圆上一点坐标
return Point(c.x + cos(a)*r, c.y + sin(a)*r);
}
};
F Angle(Vector v1){
if (v1.y >= 0)return Angle(v1, Vector(1.0, 0.0));
else return 2 * pi - Angle(v1, Vector(1.0, 0.0));
}
/*
point a,b;
int GetCC(Circle C1, Circle C2){//求两圆交点
F d = Length(C1.c - C2.c);
if (dcmp(d) == 0)
{
if (dcmp(C1.r - C2.r) == 0)return -1;//重合
else return 0;
}
if (dcmp(C1.r + C2.r - d) < 0)return 0;
if (dcmp(fabs(C1.r - C2.r) - d) > 0)return 0;

F a = Angle(C2.c - C1.c);
F da = acos((C1.r*C1.r + d * d - C2.r*C2.r) / (2 * C1.r*d));
Point p1 = C1.gpoint(a - da), p2 = C1.gpoint(a + da);
if (p1 == p2){a=b=p1;return 1;}
else {a=p1,b=p2;return 2;}
}
*/


## 极角排序

point Tmp;//选好的起点
if(a.x>0&&a.y>=0)  return 1;
if(a.x<=0&&a.y>0)  return 2;
if(a.x<0&&a.y<=0)  return 3;
if(a.x>=0&&a.y<0)  return 4;
}
bool cmp(point a,point b){
LL ans=Cross(a-Tmp,b-Tmp);
if(ans==0)return a.x<b.x;
return ans>0;
}
}


## 最小圆覆盖

double eps=1e-9;
const double pi=acos(-1);

struct node{
double x,y;
node(){}
node(double x,double y):x(x),y(y){}
};
typedef node Vector;
typedef node Point;
typedef node point;
Vector operator + (Vector a, Vector b){//向量加法
return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b){//向量减法
return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p){//向量数乘
return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p){//向量数除
return Vector(a.x / p, a.y / p);
}
double Dot(Vector a, Vector b){//内积
return a.x*b.x + a.y*b.y;
}
double Length(Vector a){//模
return sqrt(Dot(a, a));
}
double Cross(Vector a, Vector b){//外积
return a.x*b.y - a.y*b.x;
}
const double Pi=acos(-1.0);

int dcmp(double x)
{
if (fabs(x)<eps) return 0;
else if (x<0) return -1;
else return 1;
}

double lenth(node a) {return sqrt(Dot(a,a));}

node rotate(node a,double t)    //向量旋转
{
return node(a.x*cos(t)-a.y*sin(t),a.x*sin(t)+a.y*cos(t));
}

node jiao(node p,node v,node q,node w)
{
node u=p-q;
double t=Cross(w,u)/Cross(v,w);
return p+v*t;
}

node get_c(node a,node b,node c)
{
node q=(a+c)/2;    //ac中点
node v=rotate(b-a,Pi/2.0),w=rotate(c-a,Pi/2.0);   //中垂线的方向向量
if (dcmp(Cross(v,w))==0)    //平行
{
if (dcmp(lenth(a-b)+lenth(b-c)-lenth(a-c))==0)
return (a+c)/2;
if (dcmp(lenth(b-a)+lenth(a-c)-lenth(b-c))==0)
return (b+c)/2;
if (dcmp(lenth(a-c)+lenth(c-b)-lenth(a-b))==0)
return (a+b)/2;
}
return jiao(p,v,q,w);
}
node P[290];
node c;
double r;

void min_circular(int n)
{
random_shuffle(P+1,P+n+1);    //随机化
c=P[1],r=0;
//c 圆心
//r 半径
for (int i=2;i<=n;i++)
if (dcmp(lenth(c-P[i])-r)>0)    //不在圆内
{
c=P[i],r=0;
for (int j=1;j<i;j++)
if (dcmp(lenth(c-P[j])-r)>0)
{
c=(P[i]+P[j])/2.0;
r=lenth(c-P[i]);
for (int k=1;k<j;k++)
if (dcmp(lenth(c-P[k])-r)>0)
{
c=get_c(P[i],P[j],P[k]);
r=lenth(c-P[i]);
}
}
}
}

int main(){
freopen("robots.in","r",stdin);
int t;scanf("%d",&t);
while(t--){
int n;double R,rr;scanf("%d%lf%lf",&n,&R,&rr);
P[1]=node(0,0);
n++;
for(int i=2;i<=n;i++){
double x,y;scanf("%lf%lf",&x,&y);
P[i]=P[i-1]+node(x,y);
}
min_circular(n);
printf("%.9f %.9f\n",-c.x,-c.y);
}
}



## K次圆覆盖

#include<bits/stdc++.h>
using namespace std;
const int maxn=1009;
const double eps=1e-8;
const double pi=acos(-1);
int dcmp(double x) {
return fabs(x)<eps?0:(x<0?-1:1);
}
struct circle {
double x,y,r,angle;
int d;
circle() {}
circle(double x,double y,double angle=0,int d=0)
:x(x),y(y),angle(angle),d(d) {}
};
typedef circle Circle;
circle cir[maxn],tp[maxn<<1];
double area[maxn];

double sqr(double x){return x*x;}
double dis(circle a,circle b) {
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
double cross(circle a,circle b,circle c) {
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
int CirCrossCir(Circle p1, double r1,Circle p2, double r2,Circle &cp1,Circle &cp2) {
double mx = p2.x - p1.x, sx = p2.x + p1.x, mx2 = mx * mx;
double my = p2.y - p1.y, sy = p2.y + p1.y, my2 = my * my;
double sq = mx2 + my2, d = -(sq - sqr(r1 - r2)) * (sq - sqr(r1 + r2));
if (d + eps < 0)
return 0;
if (d < eps)
d = 0;
else
d = sqrt(d);
double x = mx * ((r1 + r2) * (r1 - r2) + mx * sx) + sx * my2;
double y = my * ((r1 + r2) * (r1 - r2) + my * sy) + sy * mx2;
double dx = mx * d, dy = my * d;
sq *= 2;
cp1.x = (x - dy) / sq;
cp1.y = (y + dx) / sq;
cp2.x = (x + dy) / sq;
cp2.y = (y - dx) / sq;
if (d > eps)
return 2;
else
return 1;
}

bool circmp(const Circle& u, const Circle& v) {
return dcmp(u.r - v.r) < 0;
}
bool cmp(const Circle& u, const Circle& v) {
if (dcmp(u.angle - v.angle))
return u.angle < v.angle;
return u.d > v.d;
}

double calc(Circle cir,Circle cp1,Circle cp2) {
double ans = (cp2.angle - cp1.angle) * sqr(cir.r)
- cross(cir, cp1, cp2) + cross(Circle(0, 0), cp1, cp2);
return ans / 2;
}

void CirUnion(Circle cir[], int n) {
Circle cp1, cp2;
sort(cir, cir + n, circmp);
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j)
if (dcmp(dis(cir[i], cir[j]) + cir[i].r - cir[j].r) <= 0)
cir[i].d++;
for (int i = 0; i < n; ++i) {
int tn = 0, cnt = 0;
for (int j = 0; j < n; ++j) {
if (i == j)
continue;
if (CirCrossCir(cir[i], cir[i].r, cir[j], cir[j].r,
cp2, cp1) < 2)
continue;
cp1.angle = atan2(cp1.y - cir[i].y, cp1.x - cir[i].x);
cp2.angle = atan2(cp2.y - cir[i].y, cp2.x - cir[i].x);
cp1.d = 1;
tp[tn++] = cp1;
cp2.d = -1;
tp[tn++] = cp2;
if (dcmp(cp1.angle - cp2.angle) > 0)
cnt++;
}
tp[tn++] = Circle(cir[i].x - cir[i].r, cir[i].y, pi, -cnt);
tp[tn++] = Circle(cir[i].x - cir[i].r, cir[i].y, -pi, cnt);
sort(tp, tp + tn, cmp);
int p, s = cir[i].d + tp[0].d;
for (int j = 1; j < tn; ++j) {
p = s;
s += tp[j].d;
area[p] += calc(cir[i], tp[j - 1], tp[j]);
}
}
}
int n;
void solve() {
for(int i=0; i<n; i++){
scanf("%lf%lf%lf", &cir[i].x, &cir[i].y, &cir[i].r);
cir[i].d = 1;
}
memset(area,0,sizeof area);
CirUnion(cir,n);
for(int i=1; i<=n; i++) {
area[i]-=area[i+1];
printf("[%d] = %.3f\n", i, area[i]);
}
}
int main() {
while(scanf("%d",&n)!=EOF)
solve();

return 0;
}


## 半平面交

const int maxn = 1e3;
const double EPS = 1e-5;
int T, n;
struct Point {
double x, y;
Point(double x = 0, double y = 0):x(x),y(y){}
};
typedef Point Vector;
Vector operator - (Point a, Point b) {
return Vector(b.x - a.x, b.y - a.y);
}
double operator ^ (Vector a, Vector b) {
return a.x * b.y - a.y * b.x;   //叉乘
}
struct Line {
Point s, e;
Line() {}
Line(Point a, Point b) {
s = a, e = b;
}
};
Point p[maxn];
Line L[maxn], que[maxn];

//得到极角角度
double getAngle(Vector a) {
return atan2(a.y, a.x);
}

//得到极角角度
double getAngle(Line a) {
return atan2(a.e.y - a.s.y, a.e.x - a.s.x);
}

//排序：极角小的排前面，极角相同时，最左边的排在最后面，以便去重
bool cmp(Line a, Line b) {
Vector va = a.e - a.s, vb = b.e - b.s;
double A =  getAngle(va), B = getAngle(vb);
if (fabs(A - B) < EPS)
return ((va) ^ (b.e - a.s)) >= 0;
return A < B;
}

//得到两直线相交的交点
Point getIntersectPoint(Line a, Line b) {
double a1 = a.s.y - a.e.y, b1 = a.e.x - a.s.x, c1 = a.s.x * a.e.y - a.e.x * a.s.y;
double a2 = b.s.y - b.e.y, b2 = b.e.x - b.s.x, c2 = b.s.x * b.e.y - b.e.x * b.s.y;
return Point((c1*b2-c2*b1)/(a2*b1-a1*b2), (a2*c1-a1*c2)/(a1*b2-a2*b1));
}

//判断 b,c 的交点是否在 a 的右边
bool onRight(Line a, Line b, Line c) {
Point o = getIntersectPoint(b, c);
if (((a.e - a.s) ^ (o - a.s)) < 0)
return true;
return false;
}

bool HalfPlaneIntersection() {
// que的直线两两求交点再求面积就是核的面积
sort(L, L + n, cmp);//排序
int head = 0, tail = 0, cnt = 0;//模拟双端队列
//去重，极角相同时取最后一个。
for (int i = 0; i < n - 1; i++) {
if (fabs(getAngle(L[i]) - getAngle(L[i + 1])) < EPS) {
continue;
}
L[cnt++] = L[i];
}
L[cnt++] = L[n - 1];

for (int i = 0; i < cnt; i++) {
//判断新加入直线产生的影响
while(tail - head > 1 && onRight(L[i], que[tail - 1], que[tail - 2]))
tail--;
que[tail++] = L[i];
}
//最后判断最先加入的直线和最后的直线的影响
while(tail - head > 1 && onRight(que[head], que[tail - 1], que[tail - 2]))
tail--;
if (tail - head < 3)
return false;
return true;
}

//判断输入点的顺序，如果面积 <0，说明输入的点为逆时针，否则为顺时针
bool judge() {
double ans = 0;
for (int i = 1; i < n - 1; i++) {
ans += ((p[i] - p[0]) ^ (p[i + 1] - p[0]));
}
return ans < 0;
}

int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = n - 1; i >= 0; i--) {
scanf("%lf %lf", &p[i].x, &p[i].y);
}

if (judge()) {//判断输入顺序，保证逆时针连边。
for (int i = 0; i < n; i++) {
L[i] = Line(p[(i + 1)%n], p[i]);
}
} else {
for (int i = 0; i < n; i++) {
L[i] = Line(p[i], p[(i + 1)%n]);
}
}

if (HalfPlaneIntersection())
printf("YES\n");
else
printf("NO\n");
}

return 0;
}


## 平面最近点对

const double eps=1e-6;
int dcmp(double x){return fabs(x)<eps?0:(x>0?1:-1); }

struct point{
double x,y;
bool operator<(const point&A)const{
return dcmp(x-A.x)==0?(y<A.y):(x<A.x);
}
}e[maxn],tmp[maxn];
double dis(const point &a,const point &b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(const point &a,const point &b){
return a.y<b.y;
}

#define mid (l+r>>1)
double d=1e18;
void cdq(int l,int r){
if(l==r)return ;
point M=e[mid];
cdq(l,mid),cdq(mid+1,r);
inplace_merge(e+l,e+mid+1,e+r+1,cmp);
int top=0;
rep(i,l,r){
if(fabs(e[i].x-M.x)<=d)tmp[++top]=e[i];
}
rep(i,1,top){
for(int j=i+1;j<=top&&fabs(tmp[i].y-tmp[j].y)<=d;j++){
d=min(d,dis(tmp[i],tmp[j]));
}
}
}

int main(){
int n=rd();
rep(i,1,n)scanf("%lf%lf",&e[i].x,&e[i].y);
sort(e+1,e+1+n);cdq(1,n);
printf("%.4f\n",d);
return 0;
}


## 旋转卡壳（最远对踵点对）

double RotateCalipers(P *p,int n){
if(n==2)return LengthPow(p[1]-p[2]);
double ans=-1;
p[n+1]=p[1];
// 保证q在i的前面，使得∠q_i+1_i小于180度
int q=2;
rep(i,1,n){// 枚举边i~i+1 , 如果q+1优于q , 旋转
while(Cross(p[q]-p[i+1],p[i]-p[i+1])<Cross(p[q+1]-p[i+1],p[i]-p[i+1]))q=q%n+1;
ans=max(ans,max(LengthPow(p[q]-p[i]),LengthPow(p[q+1]-p[i+1])));
}
return ans;
}

int main(){
int n;
while(scanf("%d",&n)!=EOF){
rep(i,1,n){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
Graham(p,n,ans,top);
printf("%.0f\n",round(RotateCalipers(ans,top)));
}
}


## 旋转卡壳（凸包最近距离）

#define rep(i,a,b) for(int i=a;i<=b;i++)
double DistanceToSeg(Point P, Point A, Point B) {
if(A == B)
return Length(P - A);
Vector v1 = B - A, v2 = P - A, v3 = P - B;
if(dcmp(Dot(v1, v2)) < 0)
return Length(v2);
if(dcmp(Dot(v1, v3)) > 0)
return Length(v3);
return fabs(Cross(v1, v2)) / Length(v1);
}
double SegDistancetoSeg(Point A, Point B, Point C, Point D) {
return min(min(DistanceToSeg(C, A, B), DistanceToSeg(D, A, B)),
min(DistanceToSeg(A, C, D), DistanceToSeg(B, C, D)));
}

double RotateCalipers(P *p1, int n1, P *p2, int n2) {
int q1 = 1, q2 = 1; // q1 ymin, q2 ymax
rep(i, 2, n1)
if(p1[i].y < p1[q1].y)
q1 = i;
rep(i, 2, n2)
if(p2[i].y > p2[q2].y)
q2 = i;
double ans = 1e18, tmp;
p1[n1 + 1] = p1[1], p2[n2 + 1] = p2[1];
rep(i, 1, n1) {
while(dcmp(tmp = Cross(p1[q1 + 1] - p1[q1], p2[q2 + 1] - p1[q1]) -
Cross(p1[q1 + 1] - p1[q1], p2[q2] - p1[q1])) > 0)
q2 = q2 % n2 + 1;
if(dcmp(tmp) < 0)
ans = min(ans,
DistanceToSeg(p2[q2], p1[q1], p1[q1 + 1]));
else
ans = min(ans,
SegDistancetoSeg(p1[q1], p1[q1 + 1], p2[q2], p2[q2 + 1]));
q1 = q1 % n1 + 1;
}
return ans;
}

int main() {
while(scanf("%d%d", &n1, &n2), n1 + n2) {
rep(i, 1, n1)
scanf("%lf%lf", &p1[i].x, &p1[i].y);
rep(i, 1, n2)
scanf("%lf%lf", &p2[i].x, &p2[i].y);
printf("%.5f\n", min(RotateCalipers(p1, n1, p2, n2),
RotateCalipers(p2, n2, p1, n1)));
}
}


## 旋转卡壳（凸包最小外接矩形）

double RotateCalipers(P *p,int n){
int r=2,l=2,up=2;
double area=1e18;
p[n+1]=p[1];
rep(i,1,n){
while(dcmp(Cross(p[i],p[i+1],p[up+1])-
Cross(p[i],p[i+1],p[up])<=0))up=up%n+1;
while(dcmp(Dot(p[i],p[i+1],p[r+1])-
Dot(p[i],p[i+1],p[r])>0))r=r%n+1;
if(i==1)l=r;
while(dcmp(Dot(p[i],p[i+1],p[l+1])-
Dot(p[i],p[i+1],p[l])<=0))l=l%n+1;
double d=Distance(p[i],p[i+1])*Distance(p[i],p[i+1]);
area=min(area, fabs(Cross(p[i],p[i+1],p[up]))*
fabs(Dot(p[i],p[i+1],p[r])-Dot(p[i],p[i+1],p[l]))/d );
}
return area;
}

int main(){
int t,cas=0;scanf("%d",&t);
while(t--){
printf("Case #%d:\n",++cas);
int n;scanf("%d",&n);n<<=2;
rep(i,1,n){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
Graham(p,n,ans,top);
printf("%.0f\n",RotateCalipers(ans,top));
}
}


## 圆与多边形交

int sgn(double x)
{
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
else return 1;
}
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y)
{
x = _x;
y = _y;
}
void input()
{
scanf("%lf %lf",&x,&y);
}
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);
}
double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
}
double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
Point operator * (const double &k) const
{
return Point(x * k, y * k);
}
double distance(Point p)
{
return hypot(x - p.x,y - p.y);
}
{
Point p = *this;
return fabs(atan2( fabs((a - p) ^ (b - p)),(a - p) * (b - p) ) );
}
Point operator / (const double &k) const
{
return Point(x / k, y / k);
}
double len()
{
return hypot(x,y);
}
double len2()
{
return x * x + y * y;
}
Point trunc(double r)
{
double l = len();
if(!sgn(l)) return *this;
r /= l;
return Point(x * r,y * r);
}
};
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;
e = _e;
}
double length()
{
return s.distance(e);
}
double dispointtoline(Point p)
{
return fabs( (p - s) ^ (e - s)) / length();
}
Point lineprog(Point p)
{
return s + ( ((e - s) * ((e - s) * (p - s))) / ((e - s).len2()) );
}
};
struct circle
{
Point p;
double r;
circle(){}
circle(double x,double y,double _r)
{
p = Point(x,y);
r = _r;
}
int relation(Point b)
{
double dst = b.distance(p);
if(sgn(dst - r) < 0) return 2;
else if(sgn(dst - r) == 0) return 1;
else return 0;
}
int relationline(Line v)
{
double dst = v.dispointtoline(p);
if(sgn(dst - r) < 0) return 2;
else if(sgn(dst - r) == 0) return 1;
return 0;
}
int pointcrossline(Line v,Point &p1,Point &p2)
{
if(!(*this).relationline(v)) return 0;
Point a = v.lineprog(p);
double d = v.dispointtoline(p);
d = sqrt(r * r - d * d);
if(sgn(d) == 0) {
p1 = a;
p2 = a;
return 1;
}
p1 = a + (v.e - v.s).trunc(d);
p2 = a - (v.e - v.s).trunc(d);
return 2;
}
double areatriangle(Point a,Point b)
{
if( sgn( (p - a) ^ (p - b)) == 0) return 0.0;
Point q[5];
int len = 0;
q[len++] = a;
Line l(a,b);
Point p1,p2;
if(pointcrossline(l,q[1],q[2]) == 2) {
if(sgn((a - q[1]) * (b - q[1])) < 0) q[len++] = q[1];
if(sgn((a - q[2]) * (b - q[2])) < 0) q[len++] = q[2];
}
q[len++] = b;
if(len == 4 && sgn((q[0] - q[1]) * (q[2] - q[1])) > 0) swap(q[1],q[2]);
double res = 0;
for(int i = 0; i < len - 1; i++) {
if(relation(q[i]) == 0 || relation(q[i + 1]) == 0) {
double arg = p.rad(q[i],q[i + 1]);
res += r * r * arg / 2.0;
}
else {
res += fabs((q[i] - p) ^ (q[i + 1] - p)) / 2.0;
}
}
return res;
}
};
struct polygon
{
int n;
Point p[maxp];
void input(int _n)
{
n = _n;
for(int i = 0; i < n; i++) {
p[i].input();
}
}
double areacircle(circle c)
{
double ans = 0;
for(int i = 0; i < n; i++) {
int j = (i + 1) % n;
if(sgn ( (p[j] - c.p ) ^ (p[i] - c.p ) ) >= 0)
ans += c.areatriangle(p[i],p[j]);
else ans -= c.areatriangle(p[i],p[j]);
}
return fabs(ans);
}
};
int main(void)
{
int n;
double x0,y0,v0,angle,t,g,R,x1,y1;
double sd,cd,sv,cv;
while(cin >> x0 >> y0 >> v0 >> angle >> t >> g >> R) {
if(x0 + y0 + v0 + angle + t + g + R == 0) break;
angle = (angle * 2.0 * pi ) / 360.0;
sv = v0 * cos(angle);
cv = v0 * sin(angle);
sd = sv * t;
cd = cv * t - 0.5 * g * t * t;
x1 = x0 + sd;
y1 = y0 + cd;
circle c(x1,y1,R);
polygon pl;
scanf("%d",&n);
pl.input(n);
printf("%.2lf\n",pl.areacircle(c));
}
return 0;
}

• 1
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

08-15 1795
06-02
09-25
03-31
08-14
09-04 2966
03-17
01-17
02-07 975
09-24 937
10-25
08-03 902
08-14 762