计算几何(学习)模板

点结构:

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;
}

  

 

 

 

posted @ 2012-05-22 17:21  E_star  阅读(255)  评论(0编辑  收藏  举报