码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1584 A Round Peg in a Ground Hole(凸多边形判断 + 点是否在多边形内 + 点到线段的最短距离)

时间:2020-03-03 12:50:49      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:--   外部   逆时针   大于   abs   style   clu   for   als   

题目:传送门

题意:给你一个圆和一个多边形, 判断多边形是不是凸多边形,如果是,接着判断圆是否在凸多边形内部。

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>

#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
using namespace std;

struct Point{
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) { }
};

const int N = 110;
const double eps = 1e-8;

int dcmp(double x) {
    if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
}

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); }
Point operator * (Point A, double p) { return Point(A.x * p, A.y * p); }
Point operator / (Point A, double p) { return Point(A.x / p, A.y / p); }
bool operator == (Point A, Point B) { return dcmp(A.x-B.x) == 0 && dcmp(A.y - B.y) == 0; }


double Cross(Point A, Point B) { /// 叉积
    return A.x * B.y - A.y * B.x;
}
double Dot(Point A, Point B) {
    return A.x * B.x + A.y * B.y; /// 点积
}
double Length(Point A) { return sqrt(Dot(A, A)); }

bool Onseg(Point p, Point a1, Point a2) { /// 判断点 p 是否在线段 a1a2 上(含端点)
    return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) <= 0;
}

bool SPI(Point a1, Point a2, Point b1, Point b2) { /// 判断线段a1a2与线段b1b2是否相交
    return
    max(a1.x,a2.x) >= min(b1.x,b2.x) &&
    max(b1.x,b2.x) >= min(a1.x,a2.x) &&
    max(a1.y,a2.y) >= min(b1.y,b2.y) &&
    max(b1.y,b2.y) >= min(a1.y,a2.y) &&
    dcmp(Cross(b1 - a2, a1 - a2)) * dcmp(Cross(b2 - a2, a1 - a2)) <= 0 &&
    dcmp(Cross(a1 - b2, b1 - b2)) * dcmp(Cross(a2 - b2, b1 - b2)) <= 0;
}

inline int isPointInpolygon(Point tmp, Point P[], int n) { /// 判断点是否在多边形里
    int wn = 0;
    rep(i, 0, n - 1) {
        if(Onseg(tmp, P[i], P[(i + 1) % n])) return -1; /// 边界
        int k = dcmp(Cross(P[(i + 1) % n] - P[i], tmp - P[i]));
        int d1 = dcmp(P[i].y - tmp.y);
        int d2 = dcmp(P[(i +1) % n].y - tmp.y);
        if(k > 0 && d1 <= 0 && d2 > 0) wn++;
        if(k < 0 && d2 <= 0 && d1 > 0) wn--;
    }
    if(wn != 0) return 1; /// 内部
    return 0; /// 外部
}
/// 判断凸多边形,允许共线,点可以是顺时针给出也可以是逆时针给出,编号0~n-1
bool isconvex(Point p[], int n) { 
    bool vis[3]; mem(vis, 0);
    rep(i, 0, n - 1) {
        vis[dcmp(Cross(p[(i + 1) % n] - p[i], p[(i + 2) % n] - p[i])) + 1] = 1;
        if(vis[0] && vis[2]) return false;
    }
    return true;
}

double DistanceToSegment(Point p, Point A, Point B) { /// 求点 p 到线段 AB 的最短距离
    if(A == B) return Length(p - A);
    Point v1 = B - A, v2 = p - A, v3 = p - B;
    if(dcmp(Dot(v1, v2)) < 0) return Length(v2);
    else if(dcmp(Dot(v1, v3)) > 0) return Length(v3);
    else return fabs(Cross(v1, v2)) / Length(v1);
}

Point P[N];

int main() {

    int n;
    double R, x, y;
    while(scanf("%d", &n) == 1) {
        if(n < 3) break;
        scanf("%lf %lf %lf", &R, &x, &y);
        rep(i, 0, n - 1)  scanf("%lf %lf", &P[i].x, &P[i].y);

        if(!isconvex(P, n)) { /// 不是凸多边形
            puts("HOLE IS ILL-FORMED");
            continue;
        }

        Point p = Point(x, y);

        if(isPointInpolygon(p, P, n) == 0) { /// 点不在多边形内部
            puts("PEG WILL NOT FIT");
            continue;
        }

        bool flag = 0;
        rep(i, 0, n - 1) { /// 判断点到线段的最短距离是否大于等于 R
            if(dcmp(fabs(DistanceToSegment(p, P[i], P[(i + 1) % n])) - R) < 0) {
                flag = 1;
                break;
            }
        }
        if(flag) puts("PEG WILL NOT FIT");
        else puts("PEG WILL FIT");
    }

    return 0;
}

 

POJ 1584 A Round Peg in a Ground Hole(凸多边形判断 + 点是否在多边形内 + 点到线段的最短距离)

标签:--   外部   逆时针   大于   abs   style   clu   for   als   

原文地址:https://www.cnblogs.com/Willems/p/12401486.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!