51 nod: 1298 circles and triangles

topic

Given the center and radius of the circle, and the three vertices of the triangle, ask whether the circle intersects the triangle. The intersection outputs "Yes", otherwise it outputs "No". (The area of ​​the triangle is greater than 0).
write picture description here
write picture description here

Input

Line 1: A number T, representing the number of tests entered (1 <= T <= 10000), and then every 4 lines are used to describe a set of test data.
4-1: Three numbers, the first two numbers are the coordinates xc, yc of the center of the circle, and the third number is the radius R of the circle. (-3000 <= xc, yc <= 3000, 1 <= R <= 3000)
4-2: 2 numbers, the coordinates of the first point of the triangle.
4-3: 2 numbers, the coordinates of the second point of the triangle.
4-4: 2 numbers, the coordinates of the third point of the triangle. (-3000 <= xi, yi <= 3000)

Output

A total of T lines, for each set of input data, the intersection output "Yes", otherwise output "No".

Input example

2
0 0 10
10 0
15 0
15 5
0 0 10
0 0
5 0
5 5

Output example

Yes
No

answer

To judge whether a circle intersects with a triangle, first judge the distribution of points as follows:
1. All three points are inside the circle and do not intersect
2. All three points are outside the circle, requiring special judgment
3. Others: intersection

For case 2:
1. If the circle intersects any edge, then intersect, for each edge, turn into 2
2. For each edge, find the distance from the point to the line, if the distance is greater than the radius, there is no intersection, otherwise, turn into 3
3. If the angles centered on the two triangle points are acute angles, they intersect, otherwise they do not intersect. The specific analysis is as follows:

If the distance from the center of the circle to the line segment is greater than r
, it can be directly determined that the line segment has no intersection with the circle
write picture description here

The distance from the center of the circle to the line segment is less than r
The first case:
write picture description here
In this case, we can get, OAB=OCA+Cor to , since it is a drop foot, so OCA=90 OAB>90 . Therefore, the corresponding vector dot product is less than 0. Note: It is not necessary to consider that A is the tangent point. If it is the tangent point, it is already the third case above, and the intersection is directly judged.

Second case:
write picture description here
In this case, we can get OAC+AOC=90 ,therefore OAC<90 . Empathy analysis OBC . Therefore, both angles must be acute, that is, the vector dot product is greater than 0.

Line
Equation The standard form of the line equation is: Ax+By+C=0 . Special consideration is required for vertical and horizontal lines. The formula for the distance from a point to a line is:

|Ax+By+C|A2+B2

code

#include <iostream>
#include <limits>
#include <algorithm>

using namespace std;
using ll = long long;

ll Distance(ll x1, ll y1, ll x2, ll y2)
{
    return (x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2);
}

bool isSegmentCircle(ll x, ll y, ll r,ll px1, ll py1, ll px2, ll py2)
{
    ll a, b, c;     // 直线方程的三个参数
    if (px1 == px2)
    {
        a = 1;
        b = 0;
        c = -px1;
    }
    else if (py1 == py2)
    {
        a = 0;
        b = 1;
        c = -py1;
    }
    else
    {
        a = py2 - py1;
        b = px1 - px2;
        c = px2*py1 - px1*py2;
    }
    ll dMax = r*r*(a*a + b*b);
    ll dUp = a*x + b*y + c;
    dUp = dUp*dUp;      // 点到直线距离
    if (dUp > dMax)
        return false;
    // 向量点乘
    ll sita1 = (x - px1)*(px2 - px1) + (y - py1)*(py2 - py1);
    ll sita2 = (x - px2)*(px1 - px2) + (y - py2)*(py1 - py2);
    if (sita1 > 0 && sita2 > 0)
        return true;
    return false;
}

bool isInterset(ll x, ll y, ll r, ll posX[], ll posY[])
{
    ll d1 = Distance(x, y, posX[0], posY[0]);
    ll d2 = Distance(x, y, posX[1], posY[1]);
    ll d3 = Distance(x, y, posX[2], posY[2]);
    ll d = r*r;
    if (d1 < d && d2 < d && d3 < d)
        return false;
    if (d1 > d && d2 > d && d3>d)
    {
        bool f = false;     
        f = f || isSegmentCircle(x, y,r, posX[0], posY[0], posX[1], posY[1]);
        f = f || isSegmentCircle(x, y,r, posX[1], posY[1], posX[2], posY[2]);
        f = f || isSegmentCircle(x, y,r, posX[2], posY[2], posX[0], posY[0]);
        return f;
    }
    return true;
}

int main()
{
//  freopen("input.txt", "r", stdin);
    int T;
    cin >> T;
    ll x, y, r;
    ll posX[3];
    ll posY[3];
    while (T--)
    {
        scanf("%lld%lld%lld", &x, &y, &r);
        for (int i = 0; i < 3; ++i)
            scanf("%lld%lld", &posX[i], &posY[i]);
        if (isInterset(x, y, r, posX, posY))
            cout << "Yes\n";
        else
            cout << "No\n";
    }
    return 0;
}

Ideas refer to http://blog.csdn.net/f_zyj/article/details/52066901

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325766829&siteId=291194637