51nod1298

判断线段与园是否有交。。其实很简单啊。。。就是先看两点是都在园内还是园外,然后求一个点到线段最短距离就好了

点到线段最短距离怎么弄?用向量比比划划就好了。。。

教程:http://blog.csdn.net/qq_21120027/article/details/50525835

#include
#include
#include
#include
using namespace std;
struct point
{
	double x, y;
	point(double xx, double yy) :x(xx), y(yy)
	{}
	point(){}
};
double operator*(point a, point b)
{
	return a.x*b.x + a.y*b.y;
}
double dot(point a, point b)
{
	return a.x*b.y - a.y*b.x;
}
point operator-(point a, point b)
{
	return point(a.x - b.x, a.y - b.y);
}
point operator+(point a, point b)
{
	return point(a.x + b.x, a.y + b.y);
}
double getdis(point a, point b)
{
	 double len=sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
	 if (len < 1e-8)
		 return 0;
	 else
		 return len;
}
double getmin(point a, point b, point c)
{
	double s = fabs(dot(c-a, c-b));
	return s / getdis(a, b);
}
double  judge(point a, point b, point c)
{
	if (!getdis(a, b))return getdis(a, c);
	double cc = ((b - a)*(c - a)); double kk = getdis(a, b);
	double r = ((b-a)*(c-a)) /kk;///这求得是向量a->c到向量a->b上的投影
	r = r /kk;//求得是向量a->c与向量a->b投影的比值符号代表方向
	if (r < 0)
		return getdis(a, c);
	if (r >= 1)
		return getdis(b, c);
	return getmin(a, b, c);
}
double  g(double a, double b)
{
	if (fabs(a - b) < 1e-8)
		return 0;
	else
		return a -b;
}
int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		point circle; double r;
		scanf("%lf%lf%lf", &circle.x, &circle.y, &r);
		point a, b, c;
		scanf("%lf%lf", &a.x, &a.y);
		scanf("%lf%lf", &b.x, &b.y);
		scanf("%lf%lf", &c.x, &c.y);
		double l[5];
		 l[1] = getdis(a, circle);  l[2] = getdis(b, circle);  l[3]= getdis(c, circle);
		 if (g(l[1], r)<0 && g(l[2], r)<0 && g(l[3], r)<0)
			 printf("No\n");
		 else
		 {
			 double rl[5];
				 rl[1] = judge(a, b, circle);
				 rl[2] = judge(b, c, circle);
				 rl[3] = judge(c, a, circle);
				 bool judge = false;
				 for (int i = 1; i <= 3; i++)
					 if (g(rl[i], r)<=0)
						 judge = true;
				 if (judge)
					 printf("Yes\n");
				 else
					 printf("No\n");
		 }
	}
	return 0;
}

你可能感兴趣的:(计算几何基础)