判断线段与园是否有交。。其实很简单啊。。。就是先看两点是都在园内还是园外,然后求一个点到线段最短距离就好了
点到线段最短距离怎么弄?用向量比比划划就好了。。。
教程:http://blog.csdn.net/qq_21120027/article/details/50525835
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
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;
}