这篇文章将介绍计算几何中一个基础而重要的工具——叉积。
在这之前,我们先要解决一些基本问题。
点、线段的代码表示
结合结构体或者类的知识,这里其实很好理解,但是在具体的编码过程中怎么写,这个根据个人有很大的灵活性。
比如对于点,就可以用如下的语句表达:
struct point
{
double x , y;
}
对于线段,可以用如下的语句表达:
struct line
{
point a , b ;
}
其实在这里无论是lrj的《训练指南》还是具宗万的《算法问题实战策略》都会提到,在实际问题中我们用向量作为数据结构其实更加方便,这句话是一句总结性的话语,需要编程者随着阅历的增长才会有深刻的体会。
对于向量,有如下的表述语句:
struct vector
{
double x , y ;
}
叉积概念的引入
在平面中我们为了度量一条直线的倾斜状态,为引入倾斜角这个概念。而通过在直角坐标系中建立tan α = k,我们实现了将几何关系和代数关系的衔接,这其实也是用计算机解决几何问题的一个核心,计算机做的是数值运算,因此你需要做的就是把几何关系用代数关系表达出来。而在空间中,为了表示一个平面相对空间直角坐标系的倾斜程度,我们利用一个垂直该平面的法向量来度量(因为这转化成了描述直线倾斜程度的问题)。
叉积的定义:
注意这里的θ是根据右手法则和叉乘的顺序确定的,是具有一定的方向性,这种定义直接导致了叉乘在计算几何问题上的广泛应用。
通过这个定义式,我们马上能够很容易的得到如下的运算规律。
显然这个定义式我们不怎么喜欢,因为它代数化程度还是太浅,主要就是由于角的正弦值我们不好找,但是这丝毫不影响这个定义式在应用当中的重要性,下面我们需要解决的问题就是,找到一个等价的代数化程度更高的定义式。
叉积的行列式公式(以二维为例):
其实在这里我们就能够看到,如果说是用赋予方向性的线段(line)做向量进行叉乘,那么根据定义,我们编写的cross函数中将会出现8个变量(感兴趣的同学完全可以实现一下这个过程看看有多麻烦),这对编程者来说太过繁琐,因此我们提倡将平面几何中的线段用向量vector的形式表示出来。
之所以这么详细的引出了叉乘的定义,是因为在后面它有着各类很重要的应用。
叉积的应用
一:求解三角形(平行四边形)的面积.
那么在给出三角形三个点坐标的时候,我们就可以直接利用叉乘来计算三角形的面积,相对利用海伦公式求解,结果更加精确(减少了开根号的次数)。
我们基于这个结论可以推导出任意n边形面积的计算公式。
这里需要充分理解上文给出的关于叉积定义的①式子,即严谨的来说,用叉乘算面积也是能够算出负值的。在该图中,我们这样计算多边形的面积:
二:点定位。
还是从上文给出的①式出发,我们通过代数式的胜负和夹角正弦值的对应关系来定性的描述向量之间的位置关系。
这种定性的描述,在之后计算几何杂乱的算法中会频繁出现,包括判断线段是否相交、极角排序、凸包问题等等,因此这里一定要理解透彻。