51Nod_1298 圆与三角形【判断线段与圆是否相交】

                                            51Nod_1298 圆与三角形

                                           http://www.51nod.com/Challenge/Problem.html#!#problemId=1298

题目

给出圆的圆心和半径,以及三角形的三个顶点,问圆同三角形是否相交。相交输出"Yes",否则输出"No"。(三角形的面积大于0)。

输入

第1行:一个数T,表示输入的测试数量(1 <= T <= 10000),之后每4行用来描述一组测试数据。4-1:三个数,前两个数为圆心的坐标xc, yc,第3个数为圆的半径R。(-3000 <= xc, yc <= 3000, 1 <= R <= 3000)。4-2:2个数,三角形第1个点的坐标。4-3:2个数,三角形第2个点的坐标。4-4:2个数,三角形第3个点的坐标。(-3000 <= xi, yi <= 3000)

输出

共T行,对于每组输入数据,相交输出"Yes",否则输出"No"。

样例输入

2
0 0 10
10 0
15 0
15 5
0 0 10
0 0
5 0
5 5

样例输出

Yes
No

分析

化为判断线段与圆是否相交的问题。

C++程序

#include<iostream>

using namespace std;


//点 
struct Point{
	double x,y;
	Point(){}
	Point(int x,int y):x(x),y(y){}
};

//圆 
struct Circle{
	double r,x,y;
	Circle(){};
	Circle(double r,double x,double y):r(r),x(x),y(y){} 
};

//判断直线p1p2与圆c是否相交,相交返回true,否则返回false 
bool judge(Point p1,Point p2,Circle c)
{
	bool flag1=(p1.x-c.x)*(p1.x-c.x)+(p1.y-c.y)*(p1.y-c.y)<=c.r*c.r;
	bool flag2=(p2.x-c.x)*(p2.x-c.x)+(p2.y-c.y)*(p2.y-c.y)<=c.r*c.r;
	if(flag1&&flag2)	//情况一、两点都在圆内 :一定不相交 
	  return false; 
	else if(flag1||flag2) //情况二、一个点在圆内,一个点在圆外:一定相交 
	  return true;
	else //情况三、两个点都在圆外 
	{
		double A,B,C,dist1,dist2,angle1,angle2;
		//将直线p1p2化为一般式:Ax+By+C=0的形式。先化为两点式,然后由两点式得出一般式 
		A=p1.y-p2.y;
		B=p2.x-p1.x;
		C=p1.x*p2.y-p2.x*p1.y;
		//使用距离公式判断圆心到直线ax+by+c=0的距离是否大于半径 
		dist1=A*c.x+B*c.y+C;
		dist1*=dist1;
		dist2=(A*A+B*B)*c.r*c.r;
		if(dist1>dist2)//圆心到直线p1p2的距离大于半径,不相交 
		  return false;
		angle1=(c.x-p1.x)*(p2.x-p1.x)+(c.y-p1.y)*(p2.y-p1.y);
		angle2=(c.x-p2.x)*(p1.x-p2.x)+(c.y-p2.y)*(p1.y-p2.y);
		if(angle1>0&&angle2>0)//余弦为正,则是锐角,一定相交 
		  return true; 
		else
		  return false; 
	} 
}


int main()
{
	int t;
	Circle c;//圆 
	Point p[3];//三角形的三个顶点 
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lf%lf%lf",&c.x,&c.y,&c.r);//读入圆的圆心和半径 
		for(int i=0;i<3;i++)//读入三角形的三个顶点 
		  scanf("%lf%lf",&p[i].x,&p[i].y);
		//判断3条边是否与圆相交 
		bool flag1=judge(p[0],p[1],c);
		bool flag2=judge(p[1],p[2],c);
		bool flag3=judge(p[0],p[2],c);
		if(flag1||flag2||flag3)
		  printf("Yes\n");
		else
		  printf("No\n"); 
	}
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/SongBai1997/article/details/86599794