算法导论学习笔记(五)计算几何之寻找凸包
2016-09-02 18:53
357 查看
定义:点集Q的凸包是一个最小的凸多边形P,满足Q中的每个点都在P的边界上或在P的内部。
Graham扫描法
通过排序所有点,选择一个一定是凸包中的点作为基点,再在剩余点中按相对于基点的极角排序,最后依次遍历所有点,将不符合凸多边形定义的点去除,剩下的点集便是凸包中的点。伪代码
GRAHAM-SCAN( Q) Q.sort( 0, 1, 2..., n-1) with (pi.y==pj.y)? (pi.x<pj.x) : (pi.y<pj.y) //以p0点为原点,建立极坐标 Q.sort( 1, 2..., n-1) with (pi.θ==pj.θ)? (pi.λ<pj.λ) : (pi.θ<pj.θ) let S be an empty stack PUSH( p0, S) PUSH( p1, S) PUSH( p2, S) for i = 3 to n while pi makes a nonleft turn POP( S) PUSH( pi, S) return S
代码实现
#include <cmath> #include <algorithm> const double ACCURACY = 0.0000001; typedef struct Point { int x,y; }VectorLine; VectorLine operator- ( Point a, Point b) { VectorLine c; c.x = a.x - b.x; c.y = a.y - b.y; return c; } bool cmpX( Point a, Point b ) { if( a.x == b.x ) return a.y < b.y; return a.x < b.x; } double getDistance( Point a, Point b ) { return sqrt( pow(a.x-b.x,2.0) + pow(a.y-b.y,2.0) ); } struct Node { Point point; double degree; double distance; }; void setNode(Node &a, Point source ) { double distance = getDistance( a.point, source ); double deltaY = (a.point).y - source.y; double degree = asin( deltaY/distance ); a.distance = distance; a.degree = degree; } bool cmpPoint( Node a, Node b ) { return cmpX( a.point, b.point ); } bool cmpDegree( Node a, Node b ) { if( fabs( a.degree-b.degree ) < ACCURACY ) return a.distance < b.distance; return a.degree < b.degree; } int getCrossProduct( VectorLine a, VectorLine b ) { return a.x*b.y - a.y*b.x; } bool check( Point newPoint, Point oldPoint, Point sourcePoint ) { VectorLine oldLine = oldPoint - sourcePoint; VectorLine newLine = newPoint - sourcePoint; return getCrossProduct( oldLine, newLine ) > 0; } int getConvexHull( Node *nodes, int sizeOfNodes, Point *convexHull ) { //Graham's scan std::sort( nodes, nodes+sizeOfNodes, cmpPoint ); for( int i=1; i<sizeOfNodes; i++ ) { setNode(nodes[i],nodes[0].point); } std::sort( nodes+1, nodes+sizeOfNodes, cmpDegree ); int sizeOfStack = 0; for( int i=0;i<std::min(3,sizeOfNodes);i++ ) { convexHull[sizeOfStack++] = nodes[i].point; } for( int i=3;i<sizeOfNodes;i++ ) { while( sizeOfStack > 2 && !check( nodes[i].point, convexHull[sizeOfStack-1], convexHull[sizeOfStack-2] ) ) { sizeOfStack--; } convexHull[sizeOfStack++] = nodes[i].point; } return sizeOfStack; }
Jarvis步进法
将点设为有物理特性,利用一条可弯曲的射线,将一端放在一个最左边的点上,将射线方向设为180度,逆时针旋转,所遇见的第一个为下一个凸包点,然后依次挑选,直至点为第一个点时,所选出的点集为凸包。伪代码
JARVIS( Q) Q.sort( 0, 1, 2..., n-1) with (pi.y==pj.y)? (pi.x<pj.x) : (pi.y<pj.y) let nowPoint = 0 and nextPoint = -1 while nextPoint != 0 //以p0点为原点,建立极坐标 nextPoint in Q //nextPoint为Q中极角最小的点 nowPoint = nextPoint
相关文章推荐
- 计算几何学习笔记之凸包
- 算法导论学习笔记(五)计算几何之最远点对
- 计算几何 : 凸包学习笔记 --- Graham 扫描法
- 【算法学习笔记】32.计算几何 求含最多给定点的直线 SJTU OJ 1350 穿越沙漠
- 计算几何学习笔记之多边形
- 【笔记篇】最良心的计算几何学习笔记(三)
- 【笔记篇】最良心的计算几何学习笔记(七)
- 计算几何学习笔记
- 算法学习笔记之计算几何--线段
- 【笔记篇】最良心的计算几何学习笔记(四)
- 计算几何 学习笔记
- 计算几何 学习笔记
- 【笔记篇】最良心的计算几何学习笔记(五)
- 计算几何学习笔记之点和直线
- 【笔记篇】最良心的计算几何学习笔记(一)
- 计算几何学习笔记
- 【笔记篇】最良心的计算几何学习笔记(六)
- 【笔记篇】最良心的计算几何学习笔记(二)
- 【计算几何】学习笔记
- [计算几何]【学习笔记】