solution
对于A构造一条AV,其中保证v足够大即可,判断AV是否与圆相交,分两种情况。
不相交直接判断B是否在AV上,相交则分别考虑B点是否在AV的反射线上或者在AV上
code
/*SiberianSquirrel*/
/*CuteKiloFish*/
#include <bits/stdc++.h>
using namespace std;
#define double long double
const double eps = 1e-8;
const double pi = acos(-1.0);
//`Compares a double to zero`
int sgn(double x) {
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
struct Point {
double x,y;
Point() {}
Point(double _x,double _y) {
x = _x;
y = _y;
}
void input() {
cin >> x >> y;
}
void output() {
printf("%.2f %.2f\n",x,y);
}
bool operator == (Point b)const {
return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
}
bool operator < (Point b)const {
return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
}
Point operator -(const Point &b)const {
return Point(x-b.x,y-b.y);
}
double operator ^(const Point &b)const {//叉积
return x*b.y - y*b.x;
}
double operator *(const Point &b)const {//点积
return x*b.x + y*b.y;
}
double len() {//返回长度
return hypot(x,y);//库函数
}
double len2() { //返回长度的平方
return x*x + y*y;
}
double distance(Point p) { //返回两点的距离
return hypot(x-p.x,y-p.y);
}
Point operator +(const Point &b)const {
return Point(x+b.x,y+b.y);
}
Point operator *(const double &k)const {
return Point(x*k,y*k);
}
Point operator /(const double &k)const {
return Point(x/k,y/k);
}
//`化为长度为r的向量`
Point trunc(double r) {
double l = len();
if(!sgn(l))return *this;
r /= l;
return Point(x*r,y*r);
}
};
struct Line {
Point s,e;
Line() {}
Line(Point _s,Point _e) {
s = _s;
e = _e;
}
bool operator ==(Line v) {
return (s == v.s)&&(e == v.e);
}
//`根据一个点和倾斜角angle确定直线,0<=angle<pi`
//ax+by+c=0
Line(double a,double b,double c) {
if(sgn(a) == 0) {
s = Point(0,-c/b);
e = Point(1,-c/b);
} else if(sgn(b) == 0) {
s = Point(-c/a,0);
e = Point(-c/a,1);
} else {
s = Point(0,-c/b);
e = Point(1,(-c-a)/b);
}
}
void input() {
s.input();
e.input();
}
//求线段长度
double length() {
return s.distance(e);
}
//`点和直线关系`
//`1 在左侧`
//`2 在右侧`
//`3 在直线上`
int relation(Point p) {
int c = sgn((p-s)^(e-s));
if(c < 0)return 1;
else if(c > 0)return 2;
else return 3;
}
// 点在线段上的判断
bool pointonseg(Point p) {
return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <= 0;
}
//`两向量平行(对应直线平行或重合)`
bool parallel(Line v) {
return sgn((e-s)^(v.e-v.s)) == 0;
}
//`求两直线的交点`
//`要保证两直线不平行或重合`
Point crosspoint(Line v) {
double a1 = (v.e-v.s)^(s-v.s);
double a2 = (v.e-v.s)^(e-v.s);
return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
}
//点到直线的距离
double dispointtoline(Point p) {
return fabs((p-s)^(e-s))/length();
}
//点到线段的距离
double dispointtoseg(Point p) {
if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0)
return min(p.distance(s),p.distance(e));
return dispointtoline(p);
}
//`返回点p在直线上的投影`
Point lineprog(Point p) {
return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
}
//`返回点p关于直线的对称点`
Point symmetrypoint(Point p) {
Point q = lineprog(p);
return Point(2*q.x-p.x,2*q.y-p.y);
}
};
//圆
struct circle {
Point p;//圆心
double r;//半径
circle() {}
circle(Point _p,double _r) {
p = _p;
r = _r;
}
circle(double x,double y,double _r) {
p = Point(x,y);
r = _r;
}
void input() {//输入
p.input();
cin >> r;
// scanf("%lf",&r);
}
void output() {//输出
printf("%.2lf %.2lf %.2lf\n",p.x,p.y,r);
}
bool operator == (circle v) {
return (p==v.p) && sgn(r-v.r)==0;
}
bool operator < (circle v)const {
return ((p<v.p)||((p==v.p)&&sgn(r-v.r)<0));
}
int relationseg(Line v) {
double dst = v.dispointtoseg(p);
if(sgn(dst-r) < 0)return 2;
else if(sgn(dst-r) == 0)return 1;
return 0;
}
int relationline(Line v) {
double dst = v.dispointtoline(p);
if(sgn(dst-r) < 0)return 2;
else if(sgn(dst-r) == 0)return 1;
return 0;
}
int pointcrossline(Line v,Point &p1,Point &p2) {
if(!(*this).relationline(v))return 0;
Point a = v.lineprog(p);
double d = v.dispointtoline(p);
d = sqrt(r*r-d*d);
if(sgn(d) == 0) {
p1 = a;
p2 = a;
return 1;
}
p1 = a + (v.e-v.s).trunc(d);
p2 = a - (v.e-v.s).trunc(d);
return 2;
}
};
Point a, b, v;
circle o;
double vx, vy;
void solve() {
int _, cases = 0;
cin >> _;
while(_ --) {
bool f = false;
o.input();
a.input();
v.input();
b.input();
Line av(a, a + v * 10000);
if (o.relationseg(av) == 2) {
//A会碰到圆
Point p1, p2;
o.pointcrossline(av, p1, p2);
Line op(p2, o.p);
Point _a = op.symmetrypoint(a);
Line pa(p2, a);
Line p_a(p2, p2 + (_a - p2) * 10000);
if (p_a.pointonseg(b) || pa.pointonseg(b)) f = true;
} else {
//A不会碰到圆
if (av.pointonseg(b)) f = true;
else f = false;
}
cout << "Case #" << ++ cases << ": ";
if(f) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
return 0;
}