三角形和圆的位置关系

Problem I

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 56   Accepted Submission(s) : 9
Font: Times New Roman | Verdana | Georgia
Font Size: ← →

Problem Description

在几何的世界里,有一个圆和一个三角形,现在分别告诉他们的位置,请编程判断他们之间的位置关系,是不是很简单呢?祝你好运吧~

Input

多组测试数据,第一行有一个整数t(1<=t<=100)代表case数量,对于每个case,第一行有三个整数x,y,r分别代表圆心的位置和半径,第二行有6个整数分别代表三角形的三个点(对于所有坐标绝对值小于1000,0<r<1000)

Output

每个case形如"Case #K: M",K代表case数,从1开始,M代表它们之间的关系。(如果相离或者相切输出"OO",如果三角形包含圆或者圆包含三角形输出"II",部分相交则输出"XX")

Sample Input

3
0 0 1
-5 -5 0 5 5 0
0 0 1
-2 -1 0 1 2 1
0 0 1
5 5 6 5 6 6

Sample Output

Case #1: II
Case #2: XX
Case #3: OO

#define DeBUG
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <string>
#include <set>
#include <sstream>
#include <map>
#include <list>
#include <bitset>
using namespace std ;
#define zero {0}
#define INF 0x3f3f3f3f
#define EPS 1e-9
typedef long long LL;
const double PI = acos(-1.0);
//#pragma comment(linker, "/STACK:102400000,102400000")
inline int sgn(double x)
{
    return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);
}
#define N 100005
struct Point;
typedef Point Vec;
struct Point
{
    double x, y;
    Point () {}
    Point(double a, double b)
    {
        x = a;
        y = b;
    }
    Vec operator + (const Vec &b)//点加法
    {
        return Vec(x + b.x, y + b.y);
    }
    Vec operator - (const Vec &b)//点减法
    {
        return Vec(x - b.x, y - b.y);
    }
    Vec operator * (const double &p)//点与常数相乘
    {
        return Vec(x * p, y * p);
    }
    Vec operator / (const double &p)//点除以常数
    {
        return Vec(x / p, y / p);
    }
    bool operator < (const Point &b)//平面直角坐标系中左下方的为小
    {
        return x < b.x || (sgn(x - b.x) == 0 && y < b.y);
    }
    bool operator == (const Point &b)//点相等判断
    {
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
    }
};
double dis(Point a, Point b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
inline double dotDet(Vec a, Vec b)//点乘
{
    return a.x * b.x + a.y * b.y;
}
inline double crossDet(Vec a, Vec b)//叉乘
{
    return a.x * b.y - a.y * b.x;
}
inline double crossDet(Point o, Point a, Point b)//向量叉乘
{
    return crossDet(a - o, b - o);
}
inline double triArea(Point o, Point b, Point c)//三点求三角形面积
{
    return fabs(crossDet(b - o, c - o)) / 2;
}
inline bool onSeg(Point x, Point a, Point b)//判断点在线段ab上,加上||x==a||x==b在端点也算
{
    return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0 || x == a || x == b;
}
inline double vecLen(Vec a)//求一点到原点距离
{
    return sqrt(dotDet(a, a));
}
double pt2Line(Point x, Point a, Point b)//这里已经fabs保证为正,x到直线ab的距离(投影),注意被投影向量为ax,投向ab
{
    Vec v1 = b - a, v2 = x - a;
    return fabs(crossDet(v1, v2) / vecLen(v1));
}
// Polygon class
struct Poly//平面类
{
    vector<Point> pt;//保存平面对应的端点
    Poly()
    {
        pt.clear();
    }
    ~Poly() {}
    Poly(vector<Point> pt): pt(pt) {} //使用vector进行初始化
    Point operator [](int x) const//重载[]返回对应端点
    {
        return pt[x];
    }
    int size()//返回对应平面点数
    {
        return pt.size();
    }
} ;
int ptInPoly(Point p, Poly &poly)//判断点在多边形内,用vector<Point>初始化多边形,-1在边上,0在外面,1在里面
{
    int wn = 0, sz = poly.size();
    for (int i = 0; i < sz; i++)
    {
        if (onSeg(p, poly[i], poly[(i + 1) % sz])) return -1;
        int k = sgn(crossDet(poly[(i + 1) % sz] - poly[i], p - poly[i]));
        int d1 = sgn(poly[i].y - p.y);
        int d2 = sgn(poly[(i + 1) % sz].y - p.y);
        if (k > 0 && d1 <= 0 && d2 > 0) wn++;
        if (k < 0 && d2 <= 0 && d1 > 0) wn--;
    }
    if (wn != 0) return 1;
    return 0;
}
double pt2Seg(Point x, Point a, Point b)//x在线段ab上的投影,这里保证为正
{
    if (a == b) return vecLen(x - a);
    Vec v1 = b - a, v2 = x - a, v3 = x - b;
    if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
    if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
    return fabs(crossDet(v1, v2)) / vecLen(v1);
}
bool incirle(Point p[], Point o, double r)
{
    int flag = 0;
    for (int i = 0; i < 3; i++)
    {
        if (sgn(r - dis(o, p[i])) < 0)
            return 0;
    }
    return 1;
}
int outtri1(Point p[], Point o, double r)
{
    for (int i = 0; i < 3; i++)
    {
        if (sgn(r - pt2Line(o, p[i], p[i + 1])) > 0)
        {
            return 0;
        }
    }
    return 1;
}
int outtri(Point p[], Point o, double r)
{
     for (int i = 0; i < 3; i++)
    {
        if (sgn(r - dis(o, p[i])) > 0)
            return 0;
    }
    for (int i = 0; i < 3; i++)
    {
        if (sgn(r - pt2Seg(o, p[i], p[i + 1])) > 0)
        {
            return 0;
        }
    }
    return 1;
}
int cnt = 1;
int main()
{
#ifdef DeBUGs
    freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);
#endif
    int T;
    scanf("%d", &T);
    while (T--)
    {
        double x, y, r;
        scanf("%lf%lf%lf", &x, &y, &r);
        std::vector<Point> v;
        Point p[5];
        for (int i = 0; i < 3; i++)
        {
            scanf("%lf%lf", &p[i].x, &p[i].y);
            v.push_back(p[i]);
        }
        p[3] = p[0];
        Poly tri(v);
        Point o(x, y);
        printf("Case #%d: ", cnt++);
        int flag = 0;
        if(incirle(p, o, r))//先判断三角形在圆内
        {
            printf("II\n");
        }
        else if (ptInPoly(o, tri) == 1)//如果点在三角形内两种情况
        {
            if (outtri1(p, o, r))//不相交
            {
                printf("II\n");
            }
            else
            {
                printf("XX\n");
            }
        }
        else
        {
            if (outtri(p, o, r))//圆心在三角形外且不相交
            {
                printf("OO\n");
            }
            else
                printf("XX\n");
        }
    }

    return 0;
}



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值