转载:算法导论系列--计算几何(computational geometry)
转自:http://blog.csdn.net/daly888/article/details/1486085 ,略作补充
计算几何中的对象可以是点集,线段集,面集等。如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段 (directed segment) 。如果有向线段 p1p2 的起点 p1 在坐标原点,我们可以把它称为向量/矢量 (vector)p2 。
矢量运算:
在计算几何问题中,经常要用到矢量的运算。设二维矢量 P = ( x1, y1 ) , Q = ( x2 , y2 ) ,则矢量加法定义为: P + Q = ( x1 + x2 , y1 + y2 ) ,同样的,矢量减法定义为: P - Q = ( x1 - x2 , y1 - y2 ) 。显然有性质 P + Q = Q + P , P - Q = - ( Q - P ) 。
矢量点乘(dot product) 也叫做向量内积(inner product). 设三维空间中两个向量,P(a1,a2,a3) , Q(b1,b2,b3), P·Q = a1b1 + a2b2 + a3b3. 几何意义是|P||Q| cos(PQ夹角)。
两向量点乘为0时,即这两向量互相垂直
矢量叉积(cross product) 设矢量 P = ( x1, y1 ) , Q = ( x2, y2 ) ,则矢量叉积定义为由 (0,0) 、 p1 、 p2 和 p1+p2 所组成的平行四边形的带符号的面积,即: P × Q = x1*y2 - x2*y1 ,其结果是一个标量(更高维数的叉积参阅数学书),几何意义为|P||Q| sin(PQ夹角)。显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q ) 。一般在不加说明的情况下,下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积。
设点为 Q ,线段为 AB ,判断点 Q 在直线上的依据是∠QAB = 0或180: ( Q - A ) × ( B - A ) = 0。再判断点是否在线段内,min(xA,xB) <= xQ <= max(xA,xB)且min(yA,yB) <= yQ <= max(yA,yB)。(考虑垂直和水平线段,所以要两个条件同时成立).
B = x1-x2
C = A*x1+B*y1
点到线段距离
设点为C,线段AB,C到AB距离为三角形CAB的高,假设C在AB或延长线上的投影为H。我们知道三角形面积有两种计算方法: (1) 1/2 (AB*CH), 还可以1/2 AB*AC*sin∠CAB = 1/2 |AC×AB| . 因此距离CH = |AC×AB| / |AB| 。
点在线段的垂足
接上一个话题,寻找H的坐标,线段AB确定直线Px+Qy = R, 则其垂线方程为-Qx+Py = T. 把C点坐标带入算出T的值得出方程,再求出直线交点即可。若想求C关于AB的轴对称点S,则 S = H – (C – H)
点到线段最近点
线段拐向问题
设折线段ABC,求拐向。用叉乘可以判断方向,若AC×AB 大于0,则线段右拐,小于0左拐,等于0共线。
多边形面积
判断点在多边形内
判断点P是否在顺序点集Ai确定的多边形内。过点P作一条足够长(远长于任一条边)的线段模拟过P点的射线,可随机产生一个足够大的数Q。 判断 PQ与多边形边相交的次数,若偶数则P在多边形外,奇数在多边形内(读者自己证明)。还要判断点P是否在边上。
凸包(convex hull)
设 <p1,p2,...pm> 为对其余点按以 p0 为中心的极角逆时针排序所得的点集(如果有多个点有相同的极角,除了距 p0 最远的点外全部移除
压 p0 进栈 S
压 p1 进栈 S
压 p2 进栈 S
for i ← 3 to m
do while 由 S 的栈顶元素的下一个元素、 S 的栈顶元素以及 pi 构成的折线段不拐向左侧
对 S 弹栈
压 pi 进栈 S
return S;
另外一些论题
{
double x, y;
}p[10000];
double polygon_area(int n)
{
double area=0;
for(int i=0;i<n-1;++i)
{
area+=p[i].x*p[i+1].y-p[i].y*p[i+1].x;
}
area+=p[n-1].x*p[0].y-p[n-1].y*p[0].x; //首尾相连
return fabs(area/2.0); //返回绝对值
}