计算几何(学习)模板

点结构:

struct point

{

    double x,y;

    point(double a = 0,double b = 0): x(a),y(b){}

};

  

浮点误差处理:

int dblcmp(double x)

{

	if(fabs(x) < eps)

		return 0;

	return x > 0 ? 1:-1;

}

或者

int dblcmp(double x)

{

    if (x > eps) return 1;

    else if (x < -eps) return -1;

    else return 0;

}

判断线段是否相交并求交点(规范相交)

double det(double x1, double y1, double x2, double y2)

{    //求叉积

    return x1*y2 - x2*y1;

}



double cross(Point a, Point b, Point c) 

{    //向量ab,和向量ac

    return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);

}



double dotdet(double x1, double y1, double x2, double y2) 

{    //点积

    return x1*x2 + y1*y2;

}



double dot(Point a, Point b, Point c)

{

    return dotdet(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);

}



int betweenCmp(Point a, Point b, Point c) 

{    //判断a是不是在bc范围内

    return dbcmp(dot(a, b, c));

}



bool segcross(Point a, Point b, Point c, Point d)

{

    double s1, s2;

    int d1, d2, d3, d4;

    d1 = dbcmp(s1 = cross(a, b, c));

    d2 = dbcmp(s2 = cross(a, b, d));

    d3 = dbcmp(cross(c, d, a));

    d4 = dbcmp(cross(c, d, b));

    if((d1^d2) == -2 && (d3^d4) == -2) 

    {    //规范相交

        return true;

    }

    //非规范相交

    if((d1 == 0 && betweenCmp(c, a, b) <= 0) ||

       (d2 == 0 && betweenCmp(d, a, b) <= 0) ||

       (d3 == 0 && betweenCmp(a, c, d) <= 0) ||

       (d4 == 0 && betweenCmp(b, c, d) <= 0))

        return true;

    return false;

}

  

  

叉积求多边形面积

double area(point p[],int n)

 { //这里是相对于原点(0, 0),也可以在多边形上找一个点作为向量的起点

    double s = 0;

    int i;

    p[n].x = p[0].x;

    p[n].y = p[0].y;

    for(i = 0; i < n; ++i)

        s += det(p[i].x, p[i].y, p[i+1].x, p[i+1].y);

    return fabs(s / 2.0);

}

三角形面积:

1. 海伦公式

p = (a+b+c)/2;  

S = sqrt(p*(p-a)*(p-b)*(p-c));

2:叉积求解:一直三点:

A(x1,y1),B(x2,y2),C(x3,y3);  

S = fabs(-x2 * y1 + x3*y1+x1*y2-x3*y2-x1*y3+x2*y3) / 2.0; 

判断多边形是否为凸多边形

输入p[1],p[2] ...p[n]。 令p[0] = p[n] p[n + 1] = p[1]; 

bool isconvexpg()

{

    int dir = 0;

    for (int i = 0; i <= n - 1; ++i)

    {

        int temp = dblcmp(cross(p[i],p[i + 1],p[i + 2]));

        if (!dir) dir = temp;

        if (dir*temp < 0) return false;

    }

    return true;

}

  判断一点是否在多边形内,环顾法:

double getdis(point a,point b)

{

    double x = a.x - b.x;

    double y = a.y - b.y;

    return sqrt(x*x + y*y);

}

//利用点积求角度

double getangle(point a,point b,point c)

{

    double dj = dotdet(b.x - a.x,b.y - a.y,c.x - a.x,c.y - a.y);

    double dis = getdis(a,b)*getdis(a,c);

    double tmp = dj/dis;

    return acos(tmp);

}

//判断是否在多边形内

bool IsIn()

{

    int i;

    double angle = 0.0;

    for (i = 1; i <= n; ++i)

    {

        if (dblcmp(cross(cir,p[i],p[i + 1])) >= 0)

        angle += getangle(cir,p[i],p[i + 1]);

        else

        angle -= getangle(cir,p[i],p[i + 1]);

    }

    //printf("angle == %lf\n",angle);

    if (dblcmp(angle) == 0) return false;//在外边

    else if (dblcmp(angle - pi) == 0 || dblcmp(angle + pi) == 0)//在边上

    {

        if (dblcmp(r) == 0) return true;

    }

    else if (dblcmp(angle - 2.0*pi) == 0 || dblcmp(angle + 2.0*pi) == 0)//在里面

    {

        return true;

    }

    else //在多边行顶点

    {

        if (dblcmp(r) == 0) return true;

    }

    return false;

}

  求凸包的graham_scan算法模板

//这里起点与终点肯定在凸包上,不知道怎么证明

int graham(point *p,int len)

{

    top = 0;  int i;

    //先排序,lrj黑书上的排序方法

    sort(p,p + len,cmp);

    stack[top++] = p[0];

    stack[top++] = p[1];

    //求右链

    for (i = 2; i < len; ++i)

    {

        while (top > 1 && dblcmp(cross(stack[top - 2],stack[top - 1],p[i])) <= 0) top--;

        stack[top++] = p[i];

    }

    //求左链

    int tmp = top;

    for (i =len - 2; i >= 0; --i)

    {

        while (top > tmp && dblcmp(cross(stack[top - 2],stack[top - 1],p[i]))<= 0) top--;

        stack[top++] = p[i];

    }

    return top - 1;//起点两次进栈 - 1

}

  利用凸包求最远点距离——旋转卡壳法:

int rotaing(point *p,int len)

{

    p[len] = p[0];

    int ans = 0,q = 1;

    for (int i = 0; i < len; ++i)

    {

        while (cross(p[i],p[i + 1],p[q + 1]) > cross(p[i],p[i + 1],p[q]))

        q = (q + 1)%len;

        ans = max(ans,max(dis2(p[i],p[q]),dis2(p[i + 1],p[q + 1])));

        //这里之所以计算i+1与q+1的距离是考虑到在凸多边形中存在平行边的问题

    }

    return ans;

}

  

 

 

 

你可能感兴趣的:(学习)