计算几何 全板

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
typedef long long ll;

const double pi = acos(-1.0);
const double inf = 1e100;
const double eps = 1e-6;
struct point
{
    double x,y;

    point(double a = 0, double b = 0)
    {
        x=a;
        y=b;
    }
};
point lst[1000];
int stk[1000],top=0;
int dcmp(double x, double y){
    if(fabs(x - y) < eps)
        return 0;
    if(x > y)
        return 1;
    return -1;
}
int sgn(double d){
    if(fabs(d) < eps)
        return 0;
    if(d > 0)
        return 1;
    return -1;
}
typedef point Vector;
typedef point Point;
point operator +(point a,point b)
{
    point temp;
    temp.x=a.x+b.x;
    temp.y=a.y+b.y;
    return temp;
}
point operator -(point a,point b)
{
    point temp;
    temp.x=a.x-b.x;
    temp.y=a.y-b.y;
    return temp;
}
Vector operator * (Vector A, double p)
{
    return Vector(A.x*p, A.y*p);
}
Vector operator / (Vector A, double p)
{
    return Vector(A.x/p, A.y/p);
}
//点积
double Dot(point a,point b)
{
    return a.x*b.x+a.y*b.y;
}
//叉积
double Cross(point a,point b)
{
    return a.x*b.y-a.y*b.x;
}
//返回向量长度
double Length(Vector a)
{
    return sqrt(Dot(a,a));
}
double Dis(Point p1, Point p2) { //计算 p1p2的 距离
    return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
//返回向量夹角
double Angle(Vector a,Vector b)
{
    return asin(Cross(a,b)/Length(a)/Length(b));
}
//判断是否左转
bool ToLeftTest(Vector a,Vector b)
{
    return Cross(a,b)>0;//叉积的sinθ角来判断
}
//求交点 前提 不相互平行
point GetlineIntersection(point P,Vector v,point Q,Vector w)
{

    Vector u=P-Q;
    double t=Cross(w,u)/Cross(v,w);
    return P+v*t;

}
//计算点到直线的距离
double DistanceToLine(point P, point A, point B)
{
    Vector v1 = B-A, v2 = P-A;
    return fabs(Cross(v1, v2)/Length(v1));
}
//点P在直线AB上的投影点
Point GetLineProjection(Point P, Point A, Point B){
    Vector v = B-A;
    return A+v*(Dot(v, P-A)/Dot(v, v));
}
//点是否在线段上
bool OnSegment(Point p, Point a1, Point a2){
    return dcmp(Cross(a1-p, a2-p),0) == 0 && dcmp(Dot(a1-p, a2-p),0) < 0;
}
//允许在端点处相交的线段判断
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){
    double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1);
    double c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);
    //if判断控制是否允许线段在端点处相交,根据需要添加
    if(!sgn(c1) || !sgn(c2) || !sgn(c3) || !sgn(c4)){
        bool f1 = OnSegment(b1, a1, a2);
        bool f2 = OnSegment(b2, a1, a2);
        bool f3 = OnSegment(a1, b1, b2);
        bool f4 = OnSegment(a2, b1, b2);
        bool f = (f1|f2|f3|f4);
        return f;
    }
    return (sgn(c1)*sgn(c2) < 0 && sgn(c3)*sgn(c4) < 0);
}
//求多边形面积
double PolygonArea(Point* p, int n){//p为端点集合,n为端点个数
    double s = 0;
    for(int i = 1; i < n-1; ++i)
        s += Cross(p[i]-p[0], p[i+1]-p[0]);
    return s;
}
//判断点是否在多边形内,若点在多边形内返回1,在多边形外部返回0,在多边形上返回-1
int isPointInPolygon(Point p, vector<Point> poly){
    int wn = 0;
    int n = poly.size();
    for(int i = 0; i < n; ++i){
        if(OnSegment(p, poly[i], poly[(i+1)%n])) return -1;
        int k = sgn(Cross(poly[(i+1)%n] - poly[i], p - poly[i]));
        int d1 = sgn(poly[i].y - p.y);
        int d2 = sgn(poly[(i+1)%n].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;
}
struct Line{//直线定义
    Point v, p;
    Line(Point v, Point p):v(v), p(p) {}
    Point point(double t){//返回点P = v + (p - v)*t
        return v + (p - v)*t;
    }
};
struct Circle{
    Point c;
    double r;
    Circle(Point c, double r):c(c), r(r) {}
    Point point(double a){//通过圆心角求坐标
        return Point(c.x + cos(a)*r, c.y + sin(a)*r);
    }
};
//求圆与直线交点
int getLineCircleIntersection(Line L, Circle C, double& t1, double& t2, vector<Point>& sol){
    double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
    double e = a*a + c*c, f = 2*(a*b + c*d), g = b*b + d*d - C.r*C.r;
    double delta = f*f - 4*e*g;//判别式
    if(sgn(delta) < 0)//相离
        return 0;
    if(sgn(delta) == 0){//相切
        t1 = -f /(2*e);
        t2 = -f /(2*e);
        sol.push_back(L.point(t1));//sol存放交点本身
        return 1;
    }
    //相交
    t1 = (-f - sqrt(delta))/(2*e);
    sol.push_back(L.point(t1));
    t2 = (-f + sqrt(delta))/(2*e);
    sol.push_back(L.point(t2));
    return 2;
}
//求圆得相交面积
double AreaOfOverlap(Point c1, double r1, Point c2, double r2){
    double d = Length(c1 - c2);
    if(r1 + r2 < d + eps)
        return 0.0;
    if(d < fabs(r1 - r2) + eps){
        double r = min(r1, r2);
        return pi*r*r;
    }
    double x = (d*d + r1*r1 - r2*r2)/(2.0*d);
    double p = (r1 + r2 + d)/2.0;
    double t1 = acos(x/r1);
    double t2 = acos((d - x)/r2);
    double s1 = r1*r1*t1;
    double s2 = r2*r2*t2;
    double s3 = 2*sqrt(p*(p - r1)*(p - r2)*(p - d));
    return s1 + s2 - s3;
}
bool cmp(Point p1, Point p2) { //极角排序函数 ,角度相同则距离小的在前面
    int tmp = sgn(Cross(p1 - lst[0], p2 - lst[0]));//lst为点集
    if(tmp > 0)
        return true;
    if(tmp == 0 && Dis(lst[0], p1) < Dis(lst[0], p2))
        return true;
    return false;
}
//点的编号0 ~ n - 1
//返回凸包结果stk[0 ~ top - 1]为凸包的编号
void Graham(int n) {
    int k = 0;
    Point p0;
    p0.x = lst[0].x;
    p0.y = lst[0].y;
    for(int i = 1; i < n; ++i) {
        if( (p0.y > lst[i].y) || ((p0.y == lst[i].y) && (p0.x > lst[i].x)) ) {
            p0.x = lst[i].x;
            p0.y = lst[i].y;
            k = i;
        }
    }
    lst[k] = lst[0];
    lst[0] = p0;
    sort(lst + 1, lst + n, cmp);
    if(n == 1) {
        top = 1;
        stk[0] = 0;
        return ;
    }
    if(n == 2) {
        top = 2;
        stk[0] = 0;
        stk[1] = 1;
        return ;
    }
    stk[0] = 0;
    stk[1] = 1;
    top = 2;
    for(int i = 2; i < n; ++i) {
        while(top > 1 && Cross(lst[stk[top - 1]] - lst[stk[top - 2]], lst[i] - lst[stk[top - 2]]) <= 0)
            --top;
        stk[top] = i;
        ++top;
    }
    return ;
}
//三点确定外接圆圆心坐标
Point Excenter(Point a, Point b, Point c){
    double a1 = b.x - a.x;
    double b1 = b.y - a.y;
    double c1 = (a1*a1 + b1*b1)/2;
    double a2 = c.x - a.x;
    double b2 = c.y - a.y;
    double c2 = (a2*a2 + b2*b2)/2;
    double d = a1*b2 - a2*b1;
    return Point(a.x + (c1*b2 - c2*b1)/d, a.y + (a1*c2 - a2*c1)/d);
}
double Dist2(Point p1, Point p2) { //计算距离的平方
    double ret = Dot(p1 - p2, p1 - p2);
    return ret;
}
double RotatingCalipers(Point* ch, int m) {//返回平面最大距离的平方
    if(m == 1) return 0.0;
    if(m == 2) return Dist2(ch[0], ch[1]);
    double ret = 0.0;
    ch[m] = ch[0];
    int j = 2;
    for(int i = 0; i < m; ++i) {
        while(Cross(ch[i + 1] - ch[i], ch[j] - ch[i]) < Cross(ch[i + 1] - ch[i], ch[j + 1] - ch[i]))
            j = (j + 1)%m;
        ret = max(ret, max(Dist2(ch[j], ch[i]), Dist2(ch[j], ch[i + 1])));
    }
    return ret;
}
int main()
{


}

 

#include<bits/stdc++.h>#include<iostream>using namespace std;typedef long long ll;
const double pi = acos(-1.0);const double inf = 1e100;const double eps = 1e-6;struct point{    double x,y;
    point(double a = 0, double b = 0)    {        x=a;        y=b;    }};point lst[1000];int stk[1000],top=0;int dcmp(double x, double y){    if(fabs(x - y) < eps)        return 0;    if(x > y)        return 1;    return -1;}int sgn(double d){    if(fabs(d) < eps)        return 0;    if(d > 0)        return 1;    return -1;}typedef point Vector;typedef point Point;point operator +(point a,point b){    point temp;    temp.x=a.x+b.x;    temp.y=a.y+b.y;    return temp;}point operator -(point a,point b){    point temp;    temp.x=a.x-b.x;    temp.y=a.y-b.y;    return temp;}Vector operator * (Vector A, double p){    return Vector(A.x*p, A.y*p);}Vector operator / (Vector A, double p){    return Vector(A.x/p, A.y/p);}//点积double Dot(point a,point b){    return a.x*b.x+a.y*b.y;}//叉积double Cross(point a,point b){    return a.x*b.y-a.y*b.x;}//返回向量长度double Length(Vector a){    return sqrt(Dot(a,a));}double Dis(Point p1, Point p2) { //计算 p1p2的 距离    return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));}//返回向量夹角double Angle(Vector a,Vector b){    return asin(Cross(a,b)/Length(a)/Length(b));}//判断是否左转bool ToLeftTest(Vector a,Vector b){    return Cross(a,b)>0;//叉积的sinθ角来判断}//求交点 前提 不相互平行point GetlineIntersection(point P,Vector v,point Q,Vector w){
    Vector u=P-Q;    double t=Cross(w,u)/Cross(v,w);    return P+v*t;
}//计算点到直线的距离double DistanceToLine(point P, point A, point B){    Vector v1 = B-A, v2 = P-A;    return fabs(Cross(v1, v2)/Length(v1));}//点P在直线AB上的投影点Point GetLineProjection(Point P, Point A, Point B){    Vector v = B-A;    return A+v*(Dot(v, P-A)/Dot(v, v));}//点是否在线段上bool OnSegment(Point p, Point a1, Point a2){    return dcmp(Cross(a1-p, a2-p),0) == 0 && dcmp(Dot(a1-p, a2-p),0) < 0;}//允许在端点处相交的线段判断bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){    double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1);    double c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);    //if判断控制是否允许线段在端点处相交,根据需要添加    if(!sgn(c1) || !sgn(c2) || !sgn(c3) || !sgn(c4)){        bool f1 = OnSegment(b1, a1, a2);        bool f2 = OnSegment(b2, a1, a2);        bool f3 = OnSegment(a1, b1, b2);        bool f4 = OnSegment(a2, b1, b2);        bool f = (f1|f2|f3|f4);        return f;    }    return (sgn(c1)*sgn(c2) < 0 && sgn(c3)*sgn(c4) < 0);}//求多边形面积double PolygonArea(Point* p, int n){//p为端点集合,n为端点个数    double s = 0;    for(int i = 1; i < n-1; ++i)        s += Cross(p[i]-p[0], p[i+1]-p[0]);    return s;}//判断点是否在多边形内,若点在多边形内返回1,在多边形外部返回0,在多边形上返回-1int isPointInPolygon(Point p, vector<Point> poly){    int wn = 0;    int n = poly.size();    for(int i = 0; i < n; ++i){        if(OnSegment(p, poly[i], poly[(i+1)%n])) return -1;        int k = sgn(Cross(poly[(i+1)%n] - poly[i], p - poly[i]));        int d1 = sgn(poly[i].y - p.y);        int d2 = sgn(poly[(i+1)%n].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;}struct Line{//直线定义    Point v, p;    Line(Point v, Point p):v(v), p(p) {}    Point point(double t){//返回点P = v + (p - v)*t        return v + (p - v)*t;    }};struct Circle{    Point c;    double r;    Circle(Point c, double r):c(c), r(r) {}    Point point(double a){//通过圆心角求坐标        return Point(c.x + cos(a)*r, c.y + sin(a)*r);    }};//求圆与直线交点int getLineCircleIntersection(Line L, Circle C, double& t1, double& t2, vector<Point>& sol){    double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;    double e = a*a + c*c, f = 2*(a*b + c*d), g = b*b + d*d - C.r*C.r;    double delta = f*f - 4*e*g;//判别式    if(sgn(delta) < 0)//相离        return 0;    if(sgn(delta) == 0){//相切        t1 = -f /(2*e);        t2 = -f /(2*e);        sol.push_back(L.point(t1));//sol存放交点本身        return 1;    }    //相交    t1 = (-f - sqrt(delta))/(2*e);    sol.push_back(L.point(t1));    t2 = (-f + sqrt(delta))/(2*e);    sol.push_back(L.point(t2));    return 2;}//求圆得相交面积double AreaOfOverlap(Point c1, double r1, Point c2, double r2){    double d = Length(c1 - c2);    if(r1 + r2 < d + eps)        return 0.0;    if(d < fabs(r1 - r2) + eps){        double r = min(r1, r2);        return pi*r*r;    }    double x = (d*d + r1*r1 - r2*r2)/(2.0*d);    double p = (r1 + r2 + d)/2.0;    double t1 = acos(x/r1);    double t2 = acos((d - x)/r2);    double s1 = r1*r1*t1;    double s2 = r2*r2*t2;    double s3 = 2*sqrt(p*(p - r1)*(p - r2)*(p - d));    return s1 + s2 - s3;}bool cmp(Point p1, Point p2) { //极角排序函数 ,角度相同则距离小的在前面    int tmp = sgn(Cross(p1 - lst[0], p2 - lst[0]));//lst为点集    if(tmp > 0)        return true;    if(tmp == 0 && Dis(lst[0], p1) < Dis(lst[0], p2))        return true;    return false;}//点的编号0 ~ n - 1//返回凸包结果stk[0 ~ top - 1]为凸包的编号void Graham(int n) {    int k = 0;    Point p0;    p0.x = lst[0].x;    p0.y = lst[0].y;    for(int i = 1; i < n; ++i) {        if( (p0.y > lst[i].y) || ((p0.y == lst[i].y) && (p0.x > lst[i].x)) ) {            p0.x = lst[i].x;            p0.y = lst[i].y;            k = i;        }    }    lst[k] = lst[0];    lst[0] = p0;    sort(lst + 1, lst + n, cmp);    if(n == 1) {        top = 1;        stk[0] = 0;        return ;    }    if(n == 2) {        top = 2;        stk[0] = 0;        stk[1] = 1;        return ;    }    stk[0] = 0;    stk[1] = 1;    top = 2;    for(int i = 2; i < n; ++i) {        while(top > 1 && Cross(lst[stk[top - 1]] - lst[stk[top - 2]], lst[i] - lst[stk[top - 2]]) <= 0)            --top;        stk[top] = i;        ++top;    }    return ;}//三点确定外接圆圆心坐标Point Excenter(Point a, Point b, Point c){    double a1 = b.x - a.x;    double b1 = b.y - a.y;    double c1 = (a1*a1 + b1*b1)/2;    double a2 = c.x - a.x;    double b2 = c.y - a.y;    double c2 = (a2*a2 + b2*b2)/2;    double d = a1*b2 - a2*b1;    return Point(a.x + (c1*b2 - c2*b1)/d, a.y + (a1*c2 - a2*c1)/d);}double Dist2(Point p1, Point p2) { //计算距离的平方    double ret = Dot(p1 - p2, p1 - p2);    return ret;}double RotatingCalipers(Point* ch, int m) {//返回平面最大距离的平方    if(m == 1) return 0.0;    if(m == 2) return Dist2(ch[0], ch[1]);    double ret = 0.0;    ch[m] = ch[0];    int j = 2;    for(int i = 0; i < m; ++i) {        while(Cross(ch[i + 1] - ch[i], ch[j] - ch[i]) < Cross(ch[i + 1] - ch[i], ch[j + 1] - ch[i]))            j = (j + 1)%m;        ret = max(ret, max(Dist2(ch[j], ch[i]), Dist2(ch[j], ch[i + 1])));    }    return ret;}int main(){

}

posted @ 2021-08-25 14:02  旅玖旅玖  阅读(30)  评论(0编辑  收藏  举报