几何知识及模板

来源:互联网 发布:电脑隐藏软件 编辑:程序博客网 时间:2024/06/04 07:44

参考来源:
总概括:http://dev.gameres.com/Program/Abstract/Geometry.htm
多边形与圆相交面积:http://www.cnblogs.com/lxglbk/archive/2012/08/12/2634192.html
两直线交点:http://blog.csdn.net/nightmare_ak/article/details/77917438
线段和圆的交点:https://thecodeway.com/blog/?p=932

点与线段是否相交:

bool onSegment(Point p, Point a, Point b)//点p与线段ab{    if (judgeZero(getCross(a, b, p)) != 0)        return false;    if (p._x<min(a._x, b._x) || p._x>max(a._x, b._x))//trick:垂直或平行坐标轴;        return false;    if (p._y<min(a._y, b._y) || p._y>max(a._y, b._y))        return false;    return true;}

线段与线段是否相交:

bool segmentIntersect(Point a, Point b, Point c, Point d)//线段ab与线段cd{    if (onSegment(c, a, b) || onSegment(d, a, b) || onSegment(a, c, d) || onSegment(b, c, d))        return true;    if (judgeZero(getCross(a, b, c)*getCross(a, b, d)) < 0 && judgeZero(getCross(c, d, a)*getCross(c, d, b)) < 0)//==0的特殊情况已经在前面排除        return true;    return false;}

点与直线是否相交:

bool onLine(Point p, Point a, Point b)//点p与直线ab{    return judgeZero(getCross(a, b, p)) == 0;}

直线与直线是否相交:

bool lineIntersect(Point a, Point b, Point c, Point d)//直线ab与直线cd{    if (judgeZero((a._x - b._x)*(c._y - d._y) - (c._x - d._x)*(a._y - b._y)) != 0)        return true;    if (onLine(a, c, d))//两直线重合        return true;    return false;}

线段与直线是否相交:

bool segment_intersectLine(Point a, Point b, Point c, Point d)//线段ab与直线cd{    if (judgeZero(getCross(c, d, a)*getCross(c, d, b)) <= 0)        return true;    return false;}

求交点:

Point getPoint(Point p1, Point p2, Point p3, Point p4)//求出交点,直线(线段)p1p2与直线(线段)p3p4{//t=lamta/(lamta+1),必须用t取代lamta,不然算lamta可能分母为0    double x1 = p1._x, y1 = p1._y;    double x2 = p2._x, y2 = p2._y;    double x3 = p3._x, y3 = p3._y;    double x4 = p4._x, y4 = p4._y;    double t = ((x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1)) / ((x2 - x1)*(y3 - y4) - (x3 - x4)*(y2 - y1));    return Point(x3 + t*(x4 - x3), y3 + t*(y4 - y3));}

点是否在多边形内:

bool inPolygon(Point a, int n)//点是否含于多边形{    Point b(-1e15 + a._x, a._y);//向左无穷远的线段    int count = 0;    for (int i = 0;i < n;++i)    {        Point c = polygon[i], d = polygon[(i + 1) % n];        if (onSegment(a, c, d)) //如果点在线段上,那么一定在多边形内            return true;        if (judgeZero((a._x - b._x)*(c._y - d._y) - (c._x - d._x)*(a._y - b._y)) == 0)            continue;//如果边与射线平行,trick1        if (!segmentIntersect(a, b, c, d))            continue;//如果边与射线没有交点        Point lower;        if (c._y < d._y) lower = c;        else lower = d;        if (onSegment(lower, a, b)) //如果纵坐标小的点与射线有交点,trick2            continue;        count++;    }    return count % 2 == 1;}

线段是否在多边形内:

bool segment_inPolygon(Point a, Point b, int n)//线段是否含于多边形{    if (!inPolygon(a, n) || !inPolygon(b, n))//两个端点都不在多边形内        return false;    int tot = 0;    for (int i = 0;i < n;++i)    {        Point c = polygon[i], d = polygon[(i + 1) % n];        if (onSegment(a, c, d))//以下只用记录一个交点,多的要么重复,要么一定在边上            crossp[tot++] = a;        else if (onSegment(b, c, d))            crossp[tot++] = b;        else if (onSegment(c, a, b))            crossp[tot++] = c;        else if (onSegment(d, a, b))            crossp[tot++] = d;        else if (segmentIntersect(a, b, c, d))//端点没有在线段上且相交            return false;    }    sort(crossp, crossp + tot);//按x,y排序    tot = unique(crossp, crossp + tot) - crossp;    for (int i = 0;i < tot - 1;++i)    {        Point tmp = 0.5*(crossp[i] + crossp[i + 1]);        if (!inPolygon(tmp, n))//中点不在多边形内            return false;    }    return true;}

求出直线在多边形中的长度:

double lineDis_inPolygon(Point a, Point b, int n)//求出直线在多边形内的长度{    int tot = 0;    for (int i = 0;i < n;++i)    {        Point c = polygon[i], d = polygon[(i + 1) % n];        if (onLine(c,a,b)&&onLine(d,a,b))//如果边与直线重合,记录两个端点        {            crossp[tot++] = c;            crossp[tot++] = d;        }        else if (segment_intersectLine(c, d, a, b))            crossp[tot++] = getPoint(a, b, c, d);    }    sort(crossp, crossp + tot);    tot = unique(crossp, crossp + tot) - crossp;    double ans = 0.0;    for (int i = 0;i < tot - 1;++i)    {        Point tmp = 0.5*(crossp[i] + crossp[i + 1]);        if (inPolygon(tmp, n))            ans += getDis(crossp[i], crossp[i + 1]);    }    return ans;}

点是否在圆内:

bool inCircle(Point p, Circle a)//点是否在圆内{    return judgeZero(getDis(p, a._o) - a._r) <= 0;}

点到线段的最短距离:

double dis_toSegment(Point c, Point a, Point b)//点到线段的最短距离{    Point d = a - b;    double tmp = d._y;//得到与ab垂直的向量    d._y = d._x;    d._x = -tmp;    d.toMove(c, atan2(d._y, d._x), 10.0);    Point intsect = getPoint(a, b, c, d);    if (onSegment(intsect, a, b))//垂足在线段上        return getDis(c, intsect);    return min(getDis(c, a), getDis(c, b));}

直线划分多边形:

Polygon dividePolygon(Polygon p, Point a, Point b)//直线ab划分多边形{    int n = p.size();    Polygon newp;    for (int i = 0;i < n;i++)    {        Point c = p[i], d = p[(i + 1) % n];        if (judgeZero(getCross(b, c, a)) > 0)//只记录向量ab左侧的多边形            newp.push_back(c);        if (onLine(c, a, b))//防止重复记录点            newp.push_back(c);        else if (onLine(d, a, b))            continue;        else if (lineIntersect(a, b, c, d))        {            Point tmp = getPoint(a, b, c, d);            if (onSegment(tmp, c, d))                newp.push_back(tmp);        }    }    return newp;//要判断newp.size()>=3}

多边形面积:

double polygonArea(Polygon polygon)//多边形面积{    double ans = 0.0;    for (int i = 1;i < polygon.size() - 1;i++)        ans += getCross(polygon[i], polygon[i + 1], polygon[0]);    return fabs(ans) / 2;}

圆是否含于多边形:

bool circle_inPolygon(Circle c, Polygon p)//圆含于多边形{    if (!inPolygon(c._o, p))        return false;    for (int i = 0;i < p.size();i++)    {        Point a = p[i], b = p[(i + 1) % p.size()];        if (judgeZero(dis_toSegment(c._o, a, b) - c._r) < 0)            return false;    }    return true;}

多边形是否含于圆:

bool polygon_inCircle(Circle c, Polygon p)//多边形含于圆{    for (int i = 0;i < p.size();i++)        if (!inCircle(p[i], c))            return false;    return true;}

多边形是否和圆相交(细节根据自己需要修改):

bool polygon_intersectCircle(Circle c, Polygon p)//圆含于多边形,多边形含于圆,圆和多边形相交,相切没算进去{    if (polygon_inCircle(c, p) || circle_inPolygon(c, p))        return true;    for (int i = 0;i < p.size();i++)    {        Point a = p[i], b = p[(i + 1) % p.size()];        if (judgeZero(dis_toSegment(c._o, a, b) - c._r) < 0)//算相切要<=0            return true;    }    return false;}

求线段与圆的交点:

int point_line_intersectCircle(Circle c, Point a, Point b, Point p[])//线段ab与圆c的交点{    double A = (b._x - a._x)*(b._x - a._x) + (b._y - a._y)*(b._y - a._y);    double B = 2.0 * ((b._x - a._x)*(a._x - c._o._x) + (b._y - a._y)*(a._y - c._o._y));    double C = (a._x - c._o._x)*(a._x - c._o._x) + (a._y - c._o._y)*(a._y - c._o._y) - c._r*c._r;    double deta = B*B - 4.0 * A*C;    if (judgeZero(deta) < 0) return 0;    double t1 = (-B - sqrt(deta)) / (2.0 * A);    double t2 = (-B + sqrt(deta)) / (2.0 * A);    int tot = 0;    if (judgeZero(t1) >= 0 && judgeZero(1 - t1) >= 0)        p[tot++] = Point(a._x + t1*(b._x - a._x), a._y + t1*(b._y - a._y));    if (judgeZero(t2) >= 0 && judgeZero(1 - t2) >= 0)        p[tot++] = Point(a._x + t2*(b._x - a._x), a._y + t2*(b._y - a._y));    if (tot == 2 && p[0] == p[1]) return 1;    return tot;}

求扇形的面积:

double sectorArea(Circle c, Point p1, Point p2)//扇形面积op1p2{    Point op1 = p1 - c._o, op2 = p2 - c._o;    double sita = atan2(op2._y, op2._x) - atan2(op1._y, op1._x);    while (judgeZero(sita) <= 0) sita += 2 * PI;    while (judgeZero(sita - 2 * PI) > 0) sita -= 2 * PI;    sita = min(sita, 2 * PI - sita);    return c._r*c._r*sita / 2.0;}

求一个点为圆心的三角形与圆相交的面积:

double area_triangle_fromCircle(Circle c, Point a, Point b)//圆点,a,b构成的三角形与圆相交的面积{    bool flag1 = inCircle(a, c);    bool flag2 = inCircle(b, c);    if (flag1 && flag2)//两点在圆内        return fabs(getCross(a, b, c._o) / 2.0);    Point p[2];    int tot = point_line_intersectCircle(c, a, b, p);    if (flag1) return fabs(getCross(a, p[0], c._o) / 2.0) + sectorArea(c, p[0], b);    if (flag2) return fabs(getCross(b, p[0], c._o) / 2.0) + sectorArea(c, p[0], a);    if (tot == 2) return sectorArea(c, p[0], a) + sectorArea(c, p[1], b) + fabs(getCross(p[0], p[1], c._o)) / 2;    return sectorArea(c, a, b);}

求多边形与圆相交的面积:

double area_polygon_intersectCircle(Circle c, Polygon p)//多边形和圆的相交面积{    double ans = 0.0;    for (int i = 0;i < p.size();i++)//trick:只需每相邻的点与圆心相连求相交面积,有向面积可以相互抵消    {        Point a, b;        a = p[i], b = p[(i + 1) % p.size()];        int flag = judgeZero(getCross(a, b, c._o));        ans += flag*area_triangle_fromCircle(c, a, b);    }    return fabs(ans);}

求几何中心:

Point geometryCenter(Polygon p)//几何中心{    double x = 0.0, y = 0.0;    for (int i = 0;i < p.size();++i)        x += p[i]._x, y += p[i]._y;    return Point(x / p.size(), y / p.size());}

求两圆相交面积:

double area_circle_intersectCircle(Circle c1, Circle c2)//圆相交面积{    double dis = getDis(c1._o, c2._o);    if (judgeZero(dis - c1._r - c2._r) >= 0)        return 0.0;    else if (judgeZero(fabs(c2._r - c1._r) - dis) >= 0)        return PI*min(c1._r*c1._r, c2._r*c2._r);    double sita1 = acos((c1._r*c1._r + dis*dis - c2._r*c2._r) / 2.0 / c1._r / dis);    double sita2 = acos((c2._r*c2._r + dis*dis - c1._r*c1._r) / 2.0 / c2._r / dis);    return c1._r*c1._r*sita1+ c2._r*c2._r*sita2 -dis*sin(sita1)*c1._r;}

求三角形的外接圆:

Circle getCircumcircle(Point p1, Point p2, Point p3)//三角形外接圆{    double u1 = (p2._x*p2._x - p1._x*p1._x + p2._y*p2._y - p1._y*p1._y) / 2;    double u2 = (p3._x*p3._x - p1._x*p1._x + p3._y*p3._y - p1._y*p1._y) / 2;    double d11 = p2._x - p1._x;    double d12 = p2._y - p1._y;    double d21 = p3._x - p1._x;    double d22 = p3._y - p1._y;    Circle ans;    ans._o = Point((u1*d22 - u2*d12) / (d11*d22 - d21*d12), (u2*d11 - u1*d21) / (d11*d22 - d21*d12));    ans._r = sqrt((ans._o._x - p1._x)*(ans._o._x - p1._x) + (ans._o._y - p1._y)*(ans._o._y - p1._y));    return ans;}

求凸包:

bool myCmp(Point a, Point b){    int flag = judgeZero(getCross(a, b, polygon[0]));    if (flag > 0) return true;    if (flag == 0 && judgeZero(getDis(a, polygon[0] - getDis(b, polygon[0]))) < 0)        return true;    return false;}int toGraham(Point polygon[],int n){    if (n == 1)    {        stack[0] = 0;        return 1;    }    int pos = 0;    for (int i = 1;i < n;++i)    {        if (polygon[pos].y > polygon[i].y)            pos = i;        else if (polygon[pos].y == polygon[i].y&&polygon[pos].x > polygon[i].x)            pos = i;    }    swap(polygon[0], polygon[pos]);    sort(polygon + 1, polygon + n, myCmp);    int top = 2;    stack[0] = 0, stack[1] = 1;    for (int i = 2;i < n;i++)    {        while (top>1&&getCross(polygon[i], polygon[stack[top - 2]], polygon[stack[top - 1]]) <= 0) top--;        stack[top++] = i;    }    return top;}

旋转卡壳求两点最远距离:

double  rotateCaliper(Point p[], int n){    double mxx = 0;    int t = 1;    for (int i = 0;i < n;i++)    {        while (judgeZero(fabs(getCross(p[t], p[(i + 1) % n], p[i])) - fabs(getCross(p[(t + 1) % n], p[(i + 1) % n], p[i]))) < 0)            t = (t + 1) % n;        mxx = max(mxx, getDis(p[(i + 1) % n], p[(t + 1) % n]));        mxx = max(mxx, getDis(p[i], p[t]));    }    return mxx;}

附模板:

#include<cstdio>#include<cmath>#include<iostream>#include<algorithm>#include<iomanip>#include<vector>using namespace std;const int MAXN = 200000 + 5;const double PI = acos(-1.0);const double EPS = 1e-12;double antiR;//反演圆半径int stack[MAXN], top;int judgeZero(double a)//a>0为1,<0为-1,=0为0{    return (a > EPS) - (a < -EPS);}struct Point{    double _x, _y;    Point(double x = 0.0, double y = 0.0) :_x(x), _y(y) {}    Point(const Point& p) { _x = p._x, _y = p._y; }    bool operator<(const Point& p)const    {        if (judgeZero(_x - p._x) != 0) return _x < p._x;        return _y < p._y;    }    bool operator==(const Point& p)const    {        return judgeZero(_x - p._x) == 0 && judgeZero(_y - p._y) == 0;    }    void toMove(Point a, double rad, double d)    {        _x = a._x + cos(rad)*d;        _y = a._y + sin(rad)*d;    }    Point operator+(Point a) { return Point(_x + a._x, _y + a._y); }    Point operator-(Point a) { return Point(_x - a._x, _y - a._y); }    friend Point operator*(double a, Point p) { return Point(a*p._x, a*p._y); }    friend istream& operator >> (istream& in, Point& point)    {        in >> point._x >> point._y;        return in;    }    friend ostream& operator<<(ostream& out, const Point& point)    {        out << fixed << setprecision(8) << point._x << ' ' << point._y;        return out;    }}crossp[MAXN],polygon[MAXN];double getDis(Point a, Point b){    return sqrt((a._x - b._x)*(a._x - b._x) + (a._y - b._y)*(a._y - b._y));}typedef vector<Point> Polygon;struct Circle{    Point _o;    double _r;    Circle(double x = 0.0, double y = 0.0, double r = 0.0) :_o(x, y), _r(r) {}    Circle(const Point& o, double r) :_o(o), _r(r) {}    Circle antiCircle(const Point& point)    {        Circle antic;        double dis = getDis(point, _o);        double tmp = antiR*antiR / (dis*dis - _r*_r);        antic._r = tmp*_r;        antic._o._x = point._x + tmp*(_o._x - point._x);        antic._o._y = point._y + tmp*(_o._y - point._y);        return antic;    }    friend istream& operator >> (istream& in, Circle& circle)    {        in >> circle._o >> circle._r;        return in;    }    friend ostream& operator<<(ostream& out, const Circle& circle)    {        out << circle._o << ' ' << circle._r;        return out;    }};double getCross(Point p1, Point p2, Point p){    return (p1._x - p._x)*(p2._y - p._y) - (p2._x - p._x)*(p1._y - p._y);}bool onSegment(Point p, Point a, Point b)//点p与线段ab{    if (judgeZero(getCross(a, b, p)) != 0)        return false;    if (p._x<min(a._x, b._x) || p._x>max(a._x, b._x))//trick:垂直或平行坐标轴;        return false;    if (p._y<min(a._y, b._y) || p._y>max(a._y, b._y))        return false;    return true;}bool segmentIntersect(Point a, Point b, Point c, Point d)//线段ab与线段cd{    if (onSegment(c, a, b) || onSegment(d, a, b) || onSegment(a, c, d) || onSegment(b, c, d))        return true;    if (judgeZero(getCross(a, b, c)*getCross(a, b, d)) < 0 && judgeZero(getCross(c, d, a)*getCross(c, d, b)) < 0)//==0的特殊情况已经在前面排除        return true;    return false;}bool onLine(Point p, Point a, Point b)//点p与直线ab{    return judgeZero(getCross(a, b, p)) == 0;}bool lineIntersect(Point a, Point b, Point c, Point d)//直线ab与直线cd{    if (judgeZero((a._x - b._x)*(c._y - d._y) - (c._x - d._x)*(a._y - b._y)) != 0)        return true;    if (onLine(a, c, d))//两直线重合        return true;    return false;}bool segment_intersectLine(Point a, Point b, Point c, Point d)//线段ab与直线cd{    if (judgeZero(getCross(c, d, a)*getCross(c, d, b)) <= 0)        return true;    return false;}Point point_line_intersectLine(Point p1, Point p2, Point p3, Point p4)//求出交点,直线(线段)p1p2与直线(线段)p3p4{//t=lamta/(lamta+1),必须用t取代lamta,不然算lamta可能分母为0    double x1 = p1._x, y1 = p1._y;    double x2 = p2._x, y2 = p2._y;    double x3 = p3._x, y3 = p3._y;    double x4 = p4._x, y4 = p4._y;    double t = ((x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1)) / ((x2 - x1)*(y3 - y4) - (x3 - x4)*(y2 - y1));    return Point(x3 + t*(x4 - x3), y3 + t*(y4 - y3));}bool inPolygon(Point a, Polygon polygon)//点是否含于多边形{    Point b(-1e15 + a._x, a._y);//向左无穷远的线段    int count = 0;    for (int i = 0;i < polygon.size();++i)    {        Point c = polygon[i], d = polygon[(i + 1) % polygon.size()];        if (onSegment(a, c, d)) //如果点在线段上,那么一定在多边形内            return true;        if (judgeZero((a._x - b._x)*(c._y - d._y) - (c._x - d._x)*(a._y - b._y)) == 0)            continue;//如果边与射线平行,trick1        if (!segmentIntersect(a, b, c, d))            continue;//如果边与射线没有交点        Point lower;        if (c._y < d._y) lower = c;        else lower = d;        if (onSegment(lower, a, b)) //如果纵坐标小的点与射线有交点,trick2            continue;        count++;    }    return count % 2 == 1;}bool inPolygon(Point a, Point polygon[],int n){    Point b(-1e15 + a._x, a._y);    int count = 0;    for (int i = 0;i < n;++i)    {        Point c = polygon[i], d = polygon[(i + 1) % n];        if (onSegment(a, c, d))             return true;        if (judgeZero((a._x - b._x)*(c._y - d._y) - (c._x - d._x)*(a._y - b._y)) == 0)            continue;        if (!segmentIntersect(a, b, c, d))            continue;        Point lower;        if (c._y < d._y) lower = c;        else lower = d;        if (onSegment(lower, a, b))             continue;        count++;    }    return count % 2 == 1;}bool segment_inPolygon(Point a, Point b, Polygon polygon)//线段是否含于多边形{    if (!inPolygon(a, polygon) || !inPolygon(b, polygon))//两个端点都不在多边形内        return false;    int tot = 0;    for (int i = 0;i < polygon.size();++i)    {        Point c = polygon[i], d = polygon[(i + 1) % polygon.size()];        if (onSegment(a, c, d))//以下只用记录一个交点,多的要么重复,要么一定在边上            crossp[tot++] = a;        else if (onSegment(b, c, d))            crossp[tot++] = b;        else if (onSegment(c, a, b))            crossp[tot++] = c;        else if (onSegment(d, a, b))            crossp[tot++] = d;        else if (segmentIntersect(a, b, c, d))//端点没有在线段上且相交            return false;    }    sort(crossp, crossp + tot);//按x,y排序    tot = unique(crossp, crossp + tot) - crossp;    for (int i = 0;i < tot - 1;++i)    {        Point tmp = 0.5*(crossp[i] + crossp[i + 1]);        if (!inPolygon(tmp, polygon))//中点不在多边形内            return false;    }    return true;}double lineDis_inPolygon(Point a, Point b, Polygon polygon)//求出直线在多边形内的长度{    int tot = 0;    for (int i = 0;i < polygon.size();++i)    {        Point c = polygon[i], d = polygon[(i + 1) % polygon.size()];        if (onLine(c, a, b) && onLine(d, a, b))//如果边与直线重合,记录两个端点        {            crossp[tot++] = c;            crossp[tot++] = d;        }        else if (segment_intersectLine(c, d, a, b))            crossp[tot++] = point_line_intersectLine(a, b, c, d);    }    sort(crossp, crossp + tot);    tot = unique(crossp, crossp + tot) - crossp;    double ans = 0.0;    for (int i = 0;i < tot - 1;++i)    {        Point tmp = 0.5*(crossp[i] + crossp[i + 1]);        if (inPolygon(tmp, polygon))            ans += getDis(crossp[i], crossp[i + 1]);    }    return ans;}bool inCircle(Point p, Circle a)//点是否在圆内{    return judgeZero(getDis(p, a._o) - a._r) <= 0;}double dis_toSegment(Point c, Point a, Point b)//点到线段的最短距离{    Point d = a - b;    double tmp = d._y;//得到与ab垂直的向量    d._y = d._x;    d._x = -tmp;    d.toMove(c, atan2(d._y, d._x), 10.0);    Point intsect = point_line_intersectLine(a, b, c, d);    if (onSegment(intsect, a, b))        return getDis(c, intsect);    return min(getDis(c, a), getDis(c, b));}Polygon dividePolygon(Polygon p, Point a, Point b)//直线ab划分多边形{    int n = p.size();    Polygon newp;    for (int i = 0;i < n;i++)    {        Point c = p[i], d = p[(i + 1) % n];        if (judgeZero(getCross(b, c, a)) > 0)//只记录向量ab左侧的多边形            newp.push_back(c);        if (onLine(c, a, b))//防止重复记录点            newp.push_back(c);        else if (onLine(d, a, b))            continue;        else if (lineIntersect(a, b, c, d))        {            Point tmp = point_line_intersectLine(a, b, c, d);            if (onSegment(tmp, c, d))                newp.push_back(tmp);        }    }    return newp;//要判断newp.size()>=3}double polygonArea(Polygon polygon)//多边形面积{    double ans = 0.0;    for (int i = 1;i < polygon.size() - 1;i++)        ans += getCross(polygon[i], polygon[i + 1], polygon[0]);    return fabs(ans) / 2.0;}bool circle_inPolygon(Circle c, Polygon p)//圆含于多边形{    if (!inPolygon(c._o, p))        return false;    for (int i = 0;i < p.size();i++)    {        Point a = p[i], b = p[(i + 1) % p.size()];        if (judgeZero(dis_toSegment(c._o, a, b) - c._r) < 0)            return false;    }    return true;}bool circle_inPolygon(Circle c, Point p[],int n)//圆含于多边形{    if (!inPolygon(c._o, p, n))        return false;    for (int i = 0;i < n;i++)    {        Point a = p[i], b = p[(i + 1) % n];        if (judgeZero(dis_toSegment(c._o, a, b) - c._r) < 0)            return false;    }    return true;}bool polygon_inCircle(Circle c, Polygon p)//多边形含于圆{    for (int i = 0;i < p.size();i++)        if (!inCircle(p[i], c))            return false;    return true;}bool polygon_intersectCircle(Circle c, Polygon p)//圆含于多边形,多边形含于圆,圆和多边形相交,相切没算进去{    if (polygon_inCircle(c, p) || circle_inPolygon(c, p))        return true;    for (int i = 0;i < p.size();i++)    {        Point a = p[i], b = p[(i + 1) % p.size()];        if (judgeZero(dis_toSegment(c._o, a, b) - c._r) < 0)//算相切要<=0            return true;    }    return false;}int point_line_intersectCircle(Circle c, Point a, Point b, Point p[])//线段ab与圆c的交点{    double A = (b._x - a._x)*(b._x - a._x) + (b._y - a._y)*(b._y - a._y);    double B = 2.0 * ((b._x - a._x)*(a._x - c._o._x) + (b._y - a._y)*(a._y - c._o._y));    double C = (a._x - c._o._x)*(a._x - c._o._x) + (a._y - c._o._y)*(a._y - c._o._y) - c._r*c._r;    double deta = B*B - 4.0 * A*C;    if (judgeZero(deta) < 0) return 0;    double t1 = (-B - sqrt(deta)) / (2.0 * A);    double t2 = (-B + sqrt(deta)) / (2.0 * A);    int tot = 0;    if (judgeZero(t1) >= 0 && judgeZero(1 - t1) >= 0)        p[tot++] = Point(a._x + t1*(b._x - a._x), a._y + t1*(b._y - a._y));    if (judgeZero(t2) >= 0 && judgeZero(1 - t2) >= 0)        p[tot++] = Point(a._x + t2*(b._x - a._x), a._y + t2*(b._y - a._y));    if (tot == 2 && p[0] == p[1]) return 1;    return tot;}double sectorArea(Circle c, Point p1, Point p2)//扇形面积op1p2{    Point op1 = p1 - c._o, op2 = p2 - c._o;    double sita = atan2(op2._y, op2._x) - atan2(op1._y, op1._x);    while (judgeZero(sita) <= 0) sita += 2 * PI;    while (judgeZero(sita - 2 * PI) > 0) sita -= 2 * PI;    sita = min(sita, 2 * PI - sita);    return c._r*c._r*sita / 2.0;}double area_triangle_fromCircle(Circle c, Point a, Point b)//圆点,a,b构成的三角形与圆相交的面积{    bool flag1 = inCircle(a, c);    bool flag2 = inCircle(b, c);    if (flag1 && flag2)//两点在圆内        return fabs(getCross(a, b, c._o) / 2.0);    Point p[2];    int tot = point_line_intersectCircle(c, a, b, p);    if (flag1) return fabs(getCross(a, p[0], c._o) / 2.0) + sectorArea(c, p[0], b);    if (flag2) return fabs(getCross(b, p[0], c._o) / 2.0) + sectorArea(c, p[0], a);    if (tot == 2) return sectorArea(c, p[0], a) + sectorArea(c, p[1], b) + fabs(getCross(p[0], p[1], c._o)) / 2;    return sectorArea(c, a, b);}double area_polygon_intersectCircle(Circle c, Polygon p)//多边形和圆的相交面积{    double ans = 0.0;    for (int i = 0;i < p.size();i++)//trick:只需每相邻的点与圆心相连求相交面积,有向面积可以相互抵消    {        Point a, b;        a = p[i], b = p[(i + 1) % p.size()];        int flag = judgeZero(getCross(a, b, c._o));        ans += flag*area_triangle_fromCircle(c, a, b);    }    return fabs(ans);}Point geometryCenter(Polygon p)//几何中心{    double x = 0.0, y = 0.0;    for (int i = 0;i < p.size();++i)        x += p[i]._x, y += p[i]._y;    return Point(x / p.size(), y / p.size());}double area_circle_intersectCircle(Circle c1, Circle c2)//圆相交面积{    double dis = getDis(c1._o, c2._o);    if (judgeZero(dis - c1._r - c2._r) >= 0)        return 0.0;    else if (judgeZero(fabs(c2._r - c1._r) - dis) >= 0)        return PI*min(c1._r*c1._r, c2._r*c2._r);    double sita1 = acos((c1._r*c1._r + dis*dis - c2._r*c2._r) / 2.0 / c1._r / dis);    double sita2 = acos((c2._r*c2._r + dis*dis - c1._r*c1._r) / 2.0 / c2._r / dis);    return c1._r*c1._r*sita1+ c2._r*c2._r*sita2 -dis*sin(sita1)*c1._r;}Circle getCircumcircle(Point p1, Point p2, Point p3)//三角形外接圆{    double u1 = (p2._x*p2._x - p1._x*p1._x + p2._y*p2._y - p1._y*p1._y) / 2;    double u2 = (p3._x*p3._x - p1._x*p1._x + p3._y*p3._y - p1._y*p1._y) / 2;    double d11 = p2._x - p1._x;    double d12 = p2._y - p1._y;    double d21 = p3._x - p1._x;    double d22 = p3._y - p1._y;    Circle ans;    ans._o = Point((u1*d22 - u2*d12) / (d11*d22 - d21*d12), (u2*d11 - u1*d21) / (d11*d22 - d21*d12));    ans._r = sqrt((ans._o._x - p1._x)*(ans._o._x - p1._x) + (ans._o._y - p1._y)*(ans._o._y - p1._y));    return ans;}bool myCmp(Point a, Point b){    int flag = judgeZero(getCross(a, b, polygon[0]));    if (flag > 0) return true;    if (flag == 0 && judgeZero(getDis(a, polygon[0] - getDis(b, polygon[0]))) < 0)        return true;    return false;}int toGraham(Point polygon[],int n)//求凸包{    if (n == 1)    {        stack[0] = 0;        return 1;    }    int pos = 0;    for (int i = 1;i < n;++i)    {        if (polygon[pos]._y > polygon[i]._y)            pos = i;        else if (polygon[pos]._y == polygon[i]._y&&polygon[pos]._x > polygon[i]._x)            pos = i;    }    swap(polygon[0], polygon[pos]);    sort(polygon + 1, polygon + n, myCmp);    int top = 2;    stack[0] = 0, stack[1] = 1;    for (int i = 2;i < n;i++)    {        while (top>1&&judgeZero(getCross(polygon[i], polygon[stack[top - 2]], polygon[stack[top - 1]])) <= 0) top--;//同一条直线上的点不删除的话,改成<        stack[top++] = i;    }    return top;}double  rotateCaliper(Point p[], int n){    double mxx = 0;    int t = 1;    for (int i = 0;i < n;i++)    {        while (judgeZero(fabs(getCross(p[t], p[(i + 1) % n], p[i])) - fabs(getCross(p[(t + 1) % n], p[(i + 1) % n], p[i]))) < 0)            t = (t + 1) % n;        mxx = max(mxx, getDis(p[(i + 1) % n], p[(t + 1) % n]));        mxx = max(mxx, getDis(p[i], p[t]));    }    return mxx;}int main(){    return 0;}
原创粉丝点击