计算几何常用的函数/方法

摘要:
(一)求多边形的面积代码如下:1//叉积,可以用来判断方向和求面积23doublecross{45return*-*;67}8910111213//求多边形的面积1415doubleS{1617doubleans=0;1819p[n]=p[0];2021for2223ans+=cross;2425ifans=-ans;2627returnans/2.0;2829}(二)求多边形的重心代码如下:1//求多边形的重心23Pointgrabity{45PointG;67doublesum_area=0;89for{1011doublearea=cross;1213sum_area+=area;1415G.x+=*area;1617G.y+=*area;1819}2021G.x=G.x/3/sum_area,G.y=G.y/3/sum_area;2223returnG;2425}(三)andrew算法求凸包1/**23求二维凸包Andrew算法,将所有的点按x小到大排序45删去重复的点,得到一个序列p1,p2...,然后把p1,p2放入凸包中,从p367开始当新点再前进方向左边时继续,否则,依次89删除最近加入凸包的点,直到新点再左边。
(一)求多边形的面积(用叉积计算)

代码如下:

1 //叉积,可以用来判断方向和求面积
2 
3 doublecross(Point a,Point b,Point c){
4 
5     return (c.x-a.x)*(b.y-a.y) - (b.x-a.x)*(c.y-a.y);
6 
7 }
8 
9  
10 
11  
12 
13 //求多边形的面积
14 
15 double S(Point p[],intn){
16 
17     double ans = 0;
18 
19     p[n] = p[0];
20 
21     for(int i=1;i<n;i++)
22 
23        ans += cross(p[0],p[i],p[i+1]);
24 
25     if(ans < 0) ans = -ans;
26 
27     return ans / 2.0;
28 
29 }
(二)求多边形的重心

代码如下:

1 //求多边形的重心
2 
3 Point grabity(Point p[],intn){
4 
5 Point G;
6 
7     double sum_area=0;
8 
9     for(int i=2;i<n;i++){
10 
11         double area = cross(p[0],p[i-1],p[i]);
12 
13         sum_area+=area;
14 
15         G.x+=(p[0].x+p[i-1].x+p[i].x)*area;
16 
17         G.y+=(p[0].y+p[i-1].y+p[i].y)*area;
18 
19 }
20 
21     G.x=G.x/3/sum_area,G.y=G.y/3/sum_area;
22 
23     returnG;
24 
25 }
(三)andrew算法求凸包
1 /**
2 
3 求二维凸包Andrew算法,将所有的点按x小到大(x相等,y小到大)排序
4 
5 删去重复的点,得到一个序列p1,p2...,然后把p1,p2放入凸包中,从p3
6 
7 开始当新点再前进方向左边时(可以用叉积判断方向)继续,否则,依次
8 
9 删除最近加入凸包的点,直到新点再左边。
10 
11 **/
12 
13  
14 
15 int ConvexHull(Point *p,int n,Point *stack){
16 
17     sort(p,p+n);
18 
19     n=unique(p,p+n)-p;
20 
21     int m=0;
22 
23     for(int i=0;i<n;i++){//如果不希望凸包的边上有输入的点则把两个等号去掉
24 
25         while(m>1&&cross(stack[m-2],p[i],stack[m-1])<=0) m--;
26 
27         stack[m++]=p[i];
28 
29 }
30 
31     int k=m;
32 
33     for(int i=n-2;i>=0;i--){
34 
35         while(m>k&&cross(stack[m-2],p[i],stack[m-1])<=0)m--;
36 
37         stack[m++]=p[i];
38 
39 }
40 
41     if(n>1) m--;
42 
43     returnm;
44 
45 }

(四)比较函数提高精度:

代码如下:

//判断符号,提高精度

int dcmp(doublex){

    if(fabs(x)<eps) return 0;

    else return x < 0 ? -1 : 1;

}

(五)向量/以及常见运算重载

structPoint{

    doublex,y;

    Point():x(0),y(0){}

    Point(double _x,double_y):x(_x),y(_y){}

    bool operator <(const struct Point &tmp) const{

        if(x==tmp.x) return y<tmp.y;

        return x<tmp.x;

    }

};

 

typedef Point Vector;

Vector operator +(Vector A, Vector B){

    return Vector(A.x+B.x, A.y+B.y);

}

Vector operator -(Point A, Point B){

    return Vector(A.x-B.x, A.y-B.y);

}

Vector operator * (Vector A, doublep){

    return Vector(A.x*p, A.y*p);

}

Vector operator / (Vector A, doublep){

    return Vector(A.x/p, A.y/p);

}

bool operator ==(Vector A,Vector B){

    return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0;

}

double Dot(Vector A, Vector B){//向量相乘

    return A.x*B.x + A.y*B.y;  //a*b*cos(a,b)
}

doubleLength(Vector A){

    return sqrt(Dot(A, A));    //向量的长度
}

doubleAngle(Vector A, Vector B){

    return acos(Dot(A, B) / Length(A) / Length(B));    //向量的角度
}

double Cross(Vector A, Vector B){//叉积

    return A.x*B.y - A.y*B.x;

}

/**

向量(x,y) 绕起点逆时针旋转a度。

x' = x*cosa - y*sina

y' = x*sina + y*cosa

**/
Vector Rotate(Vector A,doublea){

    return Vector (A.x*cos(a)-A.y*cos(a),A.x*sin(a)+A.y*cos(a));

}

 

double trans(doubleang){

    return ang/180*acos(-1.0);

}
(六)旋转卡壳求凸包的直径,平面最远的点对

代码如下:

//旋转卡壳求凸包的直径,平面距离最远的点对的距离

double rotatint_calipers(Point *p,intn){

    int k=1;

    int ans = 0;

    p[n]=p[0];

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

        while(fabs(Cross(p[i+1],p[k],p[i]))<fabs(Cross(p[i+1],p[k+1],p[i])))

            k=(k+1)%n;

        ans = max(ans,max(dis(p[i],p[k]),dis(p[i+1],p[k])));

    }

    returnans;

}
(七)旋转卡壳求凸包的宽度,即找一组距离最近的平行线似的凸包的点在两根线的内侧

代码如下:

1 double rotating_calipers(Point *p,intn){
2 
3     int k = 1;
4 
5     double ans = 0x7FFFFFFF;
6 
7     p[n] = p[0];
8 
9     for(int i=0;i<n;i++){
10 
11         while(fabs(cross(p[i],p[i+1],p[k])) < fabs(cross(p[i],p[i+1],p[k+1])))
12 
13              k = (k+1) %n;
14 
15         double tmp = fabs(cross(p[i],p[i+1],p[k]));
16 
17         double d   = dist(p[i],p[i+1]);
18 
19         ans = min(ans,tmp/d);
20 
21 }
22 
23     returnans;
24 
25 }

(八)求线段的中垂线

1 //求线段的中垂线  
2 
3 inline Line getMidLine(const Point &a, const Point &b) {  
4 
5     Point mid = (a +b);  
6 
7     mid.x/=2.0;  
8 
9     mid.y/=2.0;  
10 
11     Point tp = b-a;  
12 
13     return Line(mid, mid+Point(-tp.y, tp.x));  
14 
15 } 

(九)直线相关

structLine  

{  

    Point s,e;  

    Line(){}  

    Line(Point _s,Point _e)  

    {  

        s =_s;  

        e =_e;  

    }  

    bool operator ==(Line v)  

    {  

        return (s == v.s)&&(e ==v.e);  

    }  

    voidinput()  

    {  

        s.input();  

        e.input();  

    }  

    //两线段相交判断  

    //2 规范相交  

    //1 非规范相交  

    //0 不相交  

    intsegcrossseg(Line v)  

    {  

        int d1 = sgn((e-s)^(v.s-s));  

        int d2 = sgn((e-s)^(v.e-s));  

        int d3 = sgn((v.e-v.s)^(s-v.s));  

        int d4 = sgn((v.e-v.s)^(e-v.s));  

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

        return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
            (d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
            (d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
            (d4==0 && sgn((e-v.s)*(e-v.e))<=0);  

    }  

    //直线和线段相交判断  

    //-*this line   -v seg  

    //2 规范相交  

    //1 非规范相交  

    //0 不相交  

    intlinecrossseg(Line v)  

    {  

        int d1 = sgn((e-s)^(v.s-s));  

        int d2 = sgn((e-s)^(v.e-s));  

        if((d1^d2)==-2) return 2;  

        return (d1==0||d2==0);  

    }  

}; 

免责声明:文章转载自《计算几何常用的函数/方法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用swiper.js实现移动端tab切换iOS开发拓展篇—音频处理(音乐播放器6)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C/C++迭代器使用具体解释

迭代器是一种检查容器内元素并遍历元素的数据类型。能够替代下标訪问vector对象的元素。 每种容器类型都定义了自己的迭代器类型,如 vector: vector<int>::iterator iter;这符语句定义了一个名为 iter 的变量。它的数据类型是 vector<int> 定义的 iterator 类型。每一个标准库容器...

Web开发者宝典:10款流行前沿矢量图形素材

矢量图形以其鲜亮、无杂斑和醒目的外观而深受网页设计师们的喜爱。本文整理了网页设计中最为流行的20款矢量设计素材,如网页按钮,社交媒体图标和联系人图标等,希望Web开发人员会喜欢。 1. Web Buttons 2. Muted Social Media icons: 3. Contact Icon Vector Pack: 4. Simple Prom...

提高Vector容器的删除效率

vector容器是类似与一个线性数组,索引效率高,插入,删除的效率很低,需要遍历数据列表,一般情况下vector的删除操作由一下函数完成: iterator erase(iterator position) //删除一个位置 iterator erase(iterator first, iterator last)...

L3-002 特殊堆栈 (30分) vector容器的模拟、vector容器的一些用法

vector容器的简单应用,我们可以用vector维护一个有序数组,每次对要插入的数用upper_bound或者lower_bound来 为这个数找一个应该插入到vector的位置。另外再找一个数组来维护插入数的顺序,来面对pop操作 在从小到大的排序数组中, lower_bound( begin,end,num):从数组的begin位置到end-1位置...

OpenCV中的神器Image Watch

OpenCV中的神器Image Watch Image Watch是在VS2012上使用的一款OpenCV工具,能够实时显示图像和矩阵Mat的内容,跟Matlab很像,方便程序调试,相当好用。跟VS2012配合使用,简直就是一款神器!让我一下就爱上它了! 第一次看到Image Watch是今年3、4月份的时候,当时是在微博上看到新闻,点击链接的下载页面一直...

C++Vector使用方法

C++内置的数组支持容器的机制,可是它不支持容器抽象的语义。要解决此问题我们自己实现这种类。在标准C++中,用容器向量(vector)实现。容器向量也是一个类模板。 标准库vector类型使用须要的头文件:#include <vector>。vector 是一个类模板。不是一种数据类型,vector<int>是一种数据类型。Vec...