POJ 1584 A Round Peg in a Ground Hole (凸包判断+圆与多边形位置关系)

题意:先判断多边形是不是凸包,再判断圆是否在多边形内。

题解:凸包判断+圆与多边形位置关系
注意几点:
①半径可能为0
②内切也算在多边形内
③共线边

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 160;
//Compares a double to zero
int sgn(double x) {
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    else return 1;
}
//POINT
struct Point {
    double x, y;
    Point() {}
    Point(double _x, double _y) {
        x = _x;
        y = _y;
    }
    //返回两点的距离
    double distance(Point p) {
        return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    }
    bool operator == (Point b)const {
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
    }
    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;
    }
};

//LINE
struct Line {
    Point s, e;
    Line() {}
    Line(Point _s, Point _e) {
        s = _s;
        e = _e;
    }
    //求线段长度
    double length() {
        return s.distance(e);
    }
    // 点在线段上的判断
    bool pointonseg(Point p) {
        return sgn((p - s) ^ (e - s)) == 0 && sgn((p - s) * (p - e)) <= 0;
    }
    //点到直线的距离
    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);
    }
};
//圆
struct circle {
    Point p;//圆心
    double r;//半径
    circle() {}
    circle(double x, double y, double _r) {
        p = Point(x, y);
        r = _r;
    }
    //线段和圆的关系
    //比较的是圆心到线段的距离和半径的关系
    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;
    }
};
//多边形
struct polygon {
    int n;
    Point p[maxp];
    Line l[maxp];
    void getline() {
        for (int i = 0; i < n; i++) {
            l[i] = Line(p[i], p[(i + 1) % n]);
        }
    }
    //判断是不是凸的
    bool isconvex() {
        bool s[3];
        memset(s, false, sizeof(s));
        for (int i = 0; i < n; i++) {
            int j = (i + 1) % n;
            int k = (j + 1) % n;
            s[sgn((p[j]-p[i]) ^ (p[k]-p[i])) + 1] = true;
            if (s[0] && s[2])return false;
        }
        return true;
    }
    //判断点和任意多边形的关系
    // 3 点上
    // 2 边上
    // 1 内部
    // 0 外部
    int relationpoint(Point q) {
        for (int i = 0; i < n; i++) {
            if (p[i] == q)return 3;
        }
        getline();
        for (int i = 0; i < n; i++) {
            if (l[i].pointonseg(q))return 2;
        }
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            int j = (i + 1) % n;
            int k = sgn((q-p[j]) ^ (p[i]-p[j]));
            int u = sgn(p[i].y-q.y);
            int v = sgn(p[j].y-q.y);
            if (k > 0 && u < 0 && v >= 0)cnt++;
            if (k < 0 && v < 0 && u >= 0)cnt--;
        }
        return cnt != 0;
    }
    //多边形和圆关系
    // 2 圆完全在多边形内
    // 1 圆在多边形里面,碰到了多边形边界
    // 0 其它
    int relationcircle(circle c) {
        getline();
        int x = 2;
        if (relationpoint(c.p) != 1)return 0;//圆心不在内部
        for (int i = 0; i < n; i++) {
            if (c.relationseg(l[i]) == 2)return 0;
            if (c.relationseg(l[i]) == 1)x = 1;
        }
        return x;
    }
};
int n;
double r, x, y;
int main() {
    while (~scanf("%d", &n) && n >= 3) {
        scanf("%lf%lf%lf", &r, &x, &y);
        circle cir = circle(x, y, r);
        polygon pol;
        pol.n = n;
        for (int i = 0; i < n; i++) {
            scanf("%lf%lf", &x, &y);
            pol.p[i] = Point(x, y);
        }
        if (!pol.isconvex()) {
            puts("HOLE IS ILL-FORMED");
        }
        else if (r == 0) {
            if(pol.relationpoint(cir.p)) puts("PEG WILL FIT");
            else puts("PEG WILL NOT FIT");
        }
        else {
            int re = pol.relationcircle(cir);
            if (re) puts("PEG WILL FIT");
            else puts("PEG WILL NOT FIT");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值