判斷圓與三角形是否相交
阿新 • • 發佈:2019-01-01
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<algorithm> #include<ctype.h> #include<cstring> #include<queue> #include<map> #include<set> #include<stack> #include<vector> using namespace std; typedef long long ll; typedef unsigned long long ull; const int N=1e6+500; const int M=1e4+5; const ll INF=0x3f3f3f3f; const int mod=1e9+7; const double EPS = 1e-9; const double PI = acos(-1.0); struct Node{ double x; double y; }; double dis(Node a,Node b){//計算兩點之間距離 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int disline(Node a,Node b,Node c,double R){//判斷在圓外的兩點形成的線段是否與圓相交 if(c.x==b.x){//bc線段與x軸垂直 if(abs(a.x-b.x)>R)//圓心到bc直線的距離大於半徑則不相交 return 0; else{//圓心到bc直線的距離小於半徑 if(b.y>a.y&&c.y>a.y || b.y<a.y&&c.y<a.y)//若兩點y均大於(小於)圓心的y則不相交 return 0; else//其餘情況均相交 return 1; } } else if(c.y==b.y){//bc線段與y軸垂直,原理同與x軸垂直 if(abs(a.y-b.y)>R) return 0; else{ if(b.x<a.x&&c.x<a.x || b.x>a.x&&c.x>a.x) return 0; else return 1; } } else{ Node d;//bc直線上圓心r的垂點 double kbc=(b.y-c.y)/(b.x-c.x);//根據公式y=kx+b,kbc為bc直線的k,bbc為其中的b,kad、bad同理 double bbc=b.y-kbc*b.x; double kad=-1/kbc; double bad=a.y-kad*a.x; d.x=(bad-bbc)/(kbc-kad); d.y=kbc*d.x+bbc; if(dis(a,d)>R)//圓心到直線bc的距離大於半徑則不相交 return 0; else{//圓心到直線bc的距離小於半徑 if(d.x>b.x&&d.x>c.x || d.x<b.x&&d.x<c.x)//垂點d不線上段bc上則不相交 return 0; else//其餘情況則相交 return 1; } } } int solve(Node r,Node t1,Node t2,Node t3,double R){ if(dis(r,t1)<R && dis(r,t2)<R && dis(r,t3)<R)//三點均在圓內則圓與三角形不相交 return 0; //三點均在圓外,圓與三條線段均不相交,則圓與三角形不相交 if(dis(r,t1)>R && dis(r,t2)>R && dis(r,t3)>R && !disline(r,t1,t2,R) && !disline(r,t1,t3,R) && !disline(r,t2,t3,R)) return 0; return 1; } int main(){ int T; scanf("%d",&T); Node r,t1,t2,t3; double R; while(T--){ scanf("%lf%lf%lf",&r.x,&r.y,&R); scanf("%lf%lf",&t1.x,&t1.y); scanf("%lf%lf",&t2.x,&t2.y); scanf("%lf%lf",&t3.x,&t3.y); if(solve(r,t1,t2,t3,R)) printf("Yes\n"); else puts("No"); } return 0; }