- 借这道题夯实一下计算几何的基础
- 向量积:顺负逆正
- 两线交点和夹角都是借助向量工具求解的
- 分类讨论:圆弧小于180度时,减去三角形面积;大于180度时,加上三角形面积
- 割补法求面积(正难则反)
- C++中的角度以弧度制表示
#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
int s[10],t[10],r;
typedef pair<double,double> pdd;
pdd operator +(pdd a,pdd b)
{
return {a.first+b.first,a.second+b.second};
}
pdd operator -(pdd a,pdd b)
{
return {a.first-b.first,a.second-b.second};
}
pdd operator *(double a,pdd b)
{
return {a*b.first,a*b.second};
}
double operator ^(pdd a,pdd b)
{
return a.first*b.first+a.second*b.second;
}
double operator *(pdd a,pdd b)
{
return a.first*b.second-a.second*b.first;
}
pdd jiaodian(pdd a,pdd b,pdd c,pdd d)
{
pdd l1=b-a,l2=d-c;
return c+((c-a)*l1)/(l1*l2)*l2;
}
double area(vector<pdd>polygon)
{
double res=0;
for(int i=0;i<polygon.size();i++)
{
res=res+polygon[i]*polygon[(i+1)%polygon.size()];
}
return 0.5*fabs(res);
}
pdd get_dot(int rad)
{
return make_pair(cos(rad*pi/180.0)*r,sin(rad*pi/180.0)*r);
}
double len(pdd a)
{
return sqrt(a.first*a.first+a.second*a.second);
}
int sgn(double x)
{
return x>0?1:-1;
}
double shu(pdd a,pdd b)
{
double w1=(a*b);
double w2=acos((a^b)/len(a)/len(b));
if(w2<0)
{
w2=-w2;
}
else if(w2>pi)
{
w2=2*pi-w2;
}
if(w1<0)
{
w2=2*pi-w2;
}
return (w2/(2*pi))*pi*r*r-area({a,b,{0,0}})*sgn(w1);
}
void lunhuan()
{
for(int i=1;i<=5;i++)
{
s[i-1]=s[i];
t[i-1]=t[i];
}
s[5]=s[0];
t[5]=t[0];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
cin>>r;
for(int i=1;i<=5;i++)
{
cin>>s[i];
}
for(int i=1;i<=5;i++)
{
cin>>t[i];
}
double ans=pi*r*r;
for(int i=1;i<=5;i++)
{
pdd tmp=jiaodian(get_dot(s[1]),get_dot(t[4]),get_dot(s[2]),get_dot(t[5]));
ans-=area({get_dot(s[1]),get_dot(t[5]),tmp});
ans-=shu(get_dot(t[5]),get_dot(s[1]));
lunhuan();
}
cout<<fixed<<setprecision(9)<<ans<<endl;
}
return 0;
}