題目鏈接http://acm.hdu.edu.cn/showproblem.php?pid=4629
題意
給出個三角形,問被覆蓋次的面積是多少。
題解
以所有三角形線段兩兩交點的x座標爲分界線,把圖形分成若干個小區間,每個區間只包含若干個梯形,然後對於每個區間按照y座標掃描過去,累加一下答案即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e6+7;
const db eps=1e-8;
int t,n,tx,ts;
db X1,X2;
int sign(db k){if(k>eps) return 1;if(k<-eps) return -1;return 0;}
int dcmp(db k1,db k2){return sign(k1-k2);}
int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}
struct Point{
db x,y;
Point operator - (const Point k)const{return (Point){x-k.x,y-k.y};}
Point operator + (const Point k)const{return (Point){x+k.x,y+k.y};}
Point operator * (const db k)const{return (Point){x*k,y*k};}
Point operator / (const db k)const{return (Point){x/k,y/k};}
void input(){scanf("%lf%lf",&x,&y);}
};
db cross(Point k1,Point k2){return k1.x*k2.y-k1.y*k2.x;}
struct Seg{
Point s,e;
int id;
bool ck(){return inmid(s.x,e.x,X1)&&inmid(s.x,e.x,X2);}
db gety(db x){return (e.y-s.y)*(x-s.x)/(e.x-s.x)+s.y;}
db gety1(){return gety(X1);}
db gety2(){return gety(X2);}
bool operator < (Seg k){
if(dcmp(gety1(),k.gety1())==0) return gety2()<k.gety2();
return gety1()<k.gety1();
}
void output(){printf("(%f,%f) - (%f,%f)\n",s.x,s.y,e.x,e.y);}
}s[N],ns[N];
struct Triangle{
Point p[3];
}a[60];
int intersect(db l1,db r1,db l2,db r2){
if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return dcmp(r1,l2)!=-1&&dcmp(r2,l1)!=-1;
}
int checkSS(Point k1,Point k2,Point k3,Point k4){
return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&&
sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&&
sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
}
Point getLL(Point k1,Point k2,Point k3,Point k4){
db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); return (k1*w2+k2*w1)/(w1+w2);
}
db xx[N];
db ans[N];
bool vis[N];
int main()
{
scanf("%d",&t);
while(t--){
tx=ts=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
ans[i]=0;
for(int j=0;j<3;j++){
a[i].p[j].input();
}
}
for(int i=1;i<=n;i++){
for(int u=0,uu=1;u<3;u++,uu=(uu+1)%3){
s[++ts]=(Seg){a[i].p[u],a[i].p[uu],i};
if(s[ts].s.x>s[ts].e.x) swap(s[ts].s,s[ts].e);
}
}
for(int i=1;i<=ts;i++){
for(int j=i+1;j<=ts;j++){
if(cross(s[i].s-s[j].s,s[i].s-s[j].e)==0&&cross(s[i].e-s[j].s,s[i].e-s[j].e)==0) continue;
if(checkSS(s[i].s,s[i].e,s[j].s,s[j].e)){
xx[++tx]=getLL(s[i].s,s[i].e,s[j].s,s[j].e).x;
}
}
}
sort(xx+1,xx+1+tx);
int nt=1;
for(int i=2;i<=tx;i++){
if(dcmp(xx[i],xx[i-1])>0) xx[++nt]=xx[i];
}
tx=nt;
for(int i=1,j=2;j<=tx;i++,j++){
X1=xx[i],X2=xx[j],ts=0;
for(int j=1;j<=n*3;j++){
if(s[j].ck()) ns[++ts]=s[j];
vis[s[j].id]=0;
}
sort(ns+1,ns+1+ts);
int sum=0;
for(int u=1,v=2;v<=ts;u++,v++){
if(vis[ns[u].id]==false) vis[ns[u].id]=true,sum++;
else sum--;
ans[sum]+=(ns[v].gety1()-ns[u].gety1()+ns[v].gety2()-ns[u].gety2())*(xx[j]-xx[i])/2;
}
}
for(int i=1;i<=n;i++){
printf("%.10f\n",ans[i]);
}
}
}