计算几何初步

计算几何学习笔记


向量表示

当然是用点对\((a,b)\)表示一个向量啊。

点积

\(a_x\centerdot b_x+a_y\centerdot b_y\)

这个东西可以判正交:

考虑他的向量形式是:

\(\vec{a}·\vec{b}=|\vec{a}||\vec{b}|cos<\vec{a},\vec b>\)

显然\(cos(90°)\)=0,然后就可以如果点积为0,就垂直。

叉积

\(a.x*b.y-a.y*b.x\)

这是三角形有向面积的一半。

证明如下:

叉积证明放图在这里

\[S_{\triangle ABC}= x_2*y_1-\frac{x_1*y_1}{2}-\frac{x_2*y_2}{2}-\frac{\triangle x*\triangle y}{2} \\ =x_2*y_1-\frac{x_1*y_1}{2}-\frac{x_2*y_2}{2}-\frac{x_2\centerdot y_1}{2}+\frac{x_2\centerdot y_2}{2}-\frac{x_1\centerdot y_2}{2}+\frac{x_1\centerdot y_1}{2} \\ =x_2*y_1-\frac{x_2\centerdot y_1+x_1 \centerdot y_2}{2} \\ =|\frac{x_2\centerdot y_1-x_1\centerdot y_2}{2}| \]

当然这个上面的推断是无向面积,有向面积换一下点就好了。

当然叉积可以判平行啊,写成向量的形式就是:

\(\vec{a}\centerdot \vec{b}=|\vec{a}||\vec{b}|sin<\vec{a},\vec{b}>\)

看到sin不就直接和上面一样的判就好了。

如果向量1在逆时针(就是在左边),叉积为负,否则叉积为正。

判交

可以用点积+叉积判交。

考虑下面两种情况:

  1. 不平行,显然考虑点积和叉积判断点q在不在两条线段上就好了。
  2. 平行,这个直接搞(注意平行可能也有交)

转角

考虑一下如果一个向量在单位圆上,与x轴的夹角是\(\beta(\beta\leq 180°)\)显然他就是\((R*sin\beta,R*cos\beta)​\),那么现在R就是他的模长(其实就是长度)。

然后如果增加的是\(\alpha\)的话,直接和差角公式搞一下就好了。

极角

考虑怎么算上面那一个\(\beta\),直接\(acos(a.y,a.x)\)

凸包

这个东西的定义很简单不是吗?

求解:一般性用Graham扫描吧...

void Graham()
{
    //p数组先极角排序(p[1]是边界点,先算p[1])
    s[top=1]=p[1];
	for(int i=2;i<=n;i++)
		p[i].ang=atan2(p[i].y-p[1].y,p[i].x-p[1].x);
	sort(p+2,p+n+1,cmpang);s[++top]=p[2];
	for(int i=2;i<=n;i++)
	{
		while(top>1 && cross(p[i]-s[top],p[i]-s[top-1])>=0)top--;
		s[++top]=p[i];
	}
}

凸包面积

直接按照边划分成三角形然后cross算面积就好了.

最小圆覆盖

枚举第一个点,考虑当前圆是否包含了这个点,如果没有,则把圆变成以这个点为圆心,半径为0的圆。再枚举第二个点,考虑圆是否包含了这个点,如果没有,则把圆变成以这两个点的中点为圆心,半径为两点距离一半的圆。再枚举第三个点,节点是否在圆内,如果不在,则把圆直接变成这三个点的外接圆

这个算法看上去是\(O(n^3)​\)的,但是把点随机打乱之后是\(O(n)​\)的.

void GetCircle(point *p,int n){
	random_shuffle(&p[1],&p[n+1]);
	for(int i=1;i<=n;i++)
		if(Dis(O.o,p[i])>O.r){
			O.o=p[i];O.r=0;
			for(int j=1;j<i;j++)
				if(Dis(O.o,p[j])>O.r){
					O.o=(p[i]+p[j])*0.5;O.r=Dis(p[i],p[j])*0.5;
					for(int k=1;k<j;k++)
						if(Dis(O.o,p[k])>O.r){
							O.o=Intersecion(gethalfline((line){p[i],p[j]-p[i]}),gethalfline((line){p[i],p[k]-p[i]}));
							O.r=Dis(O.o,p[i]);
						}
				}
		}
	printf("%.10lf\n%.10lf %.10lf\n",O.r,O.o.x,O.o.y);
}

自适应Simpson法

这个随便背一下模板就好了.

posted @ 2019-01-28 15:04  QwQGJH  阅读(268)  评论(2编辑  收藏  举报