sgu233The Greatest Angle(计算几何)

题意:

给出一个圆O和严格在圆内的两点A,B,在圆上求一点C使得∠ACB最大。

tip:

A,B,C所构成的外接圆与圆O相切时最大。因为AB所在的圆,无论半径多大,所对应的圆周角是固定的,且半径越大角度越小,所有在相切时最好。
解方程:
设小圆的圆心为p,两圆相切:
OP = R-r = R-sqrt(pc^2+AC^2)
因为∠PCO是定值,(360°-(∠OCP+90°))
所以在三角形pco中做余弦定理,
OP^2 = cp^2+OC^2-2*CP*CO*cos∠pco
只有未知数PC。。可求出,然后求出P点坐标,直线OP可表示,向量OP,R乘起来+O就是切点坐标了。。。

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

const double eps = 1e-8;
const double pi = acos(-1.0);
struct Tpoint{
    double x, y;
    Tpoint(double x = 0, double y = 0):x(x),y(y){}
}O, A, B, C, vCP, vAC, oP, D;
double R, r,AC, CO, cosPCO, OCA, P, Q, a, b, c, deita;
double PC,p, q;
Tpoint operator + (const Tpoint a, const Tpoint b) {return Tpoint(a.x+b.x, a.y+b.y);}
Tpoint operator - (const Tpoint a, const Tpoint b) {return Tpoint(a.x-b.x, a.y-b.y);}
Tpoint operator * (const Tpoint a, double k) {return Tpoint(a.x*k, a.y*k);}
Tpoint operator / (const Tpoint a, double k) {return Tpoint(a.x/k, a.y/k);}
double length(Tpoint x) {return sqrt(x.x*x.x+x.y*x.y);}
Tpoint unit(Tpoint x) { Tpoint a; a= x/length(x);return a;}

double dis2(const Tpoint a, const Tpoint b) {return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
double dis(const Tpoint a, const Tpoint b) {return sqrt(dis2(a, b));}
bool sign(double x){
    if(fabs(x) <= eps) return true;
    return false;
}

double calc_angle(const Tpoint a, const Tpoint b, const Tpoint c){
    double ac2 = dis2(a, c), bc2 = dis2(b, c), ab2 = dis2(a, b);
    if(sign(bc2) || sign(ab2)) return 0;
    return acos((ac2-bc2-ab2)/(2*sqrt(bc2)*sqrt(ab2)));
}

bool check(const Tpoint &P){
    if(sign(dis(P, O)+r-R)) return true;
    return false;
}
void init(){
    scanf("%lf%lf%lf", &O.x, &O.y,&R);
    scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);
    C = (A+B)/2;AC = dis(A, C), CO = dis(C, O);
    OCA = calc_angle(A, C, O);
    cosPCO = cos(2*pi-OCA+pi/2);
    P = R*R-dis2(O, C)+dis2(A, C);Q = CO*cosPCO;///p-2R * AP+ 2Q*cp = 0;
}
void sov(){
    a = 4*Q*Q-4*R*R, b = 4*P*Q, c = P*P-4*dis2(A, C)*R*R;
    if(sign(a)) PC = -c/b;
    else{
        deita = b*b-4*a*c;
        if(sign(deita)) deita = 0;
        p = -b/(2*a), q = sqrt(deita)/(2*a);
        PC = p+q;
        if((p+q)*(p+q) > (p-q)*(p-q)) PC = p-q;
    }
    r = sqrt(PC*PC+dis2(A, C));///AP
    vAC = C-A, vAC = vAC/length(vAC);
    vCP = Tpoint(-vAC.y, vAC.x), PC = fabs(PC);
    if(check(C+vCP*PC)) oP = C+vCP*PC;
    else oP = C-vCP*PC;
    D = unit(oP-O)*R+O;
    printf("%.6f %.6f",D.x,D.y);puts("");
}
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        init();
        sov();
    }
    return 0;
}
阅读更多
版权声明:转我原创记得说你是我的脑残粉哟 https://blog.csdn.net/zjy2015302395/article/details/77552131
个人分类: acm 基本算法
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭