• 计算几何初步


    计算几何学习笔记


    向量表示

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

    点积

    (a_xcenterdot b_x+a_ycenterdot 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_{ riangle ABC}= x_2*y_1-frac{x_1*y_1}{2}-frac{x_2*y_2}{2}-frac{ riangle x* riangle y}{2} \ =x_2*y_1-frac{x_1*y_1}{2}-frac{x_2*y_2}{2}-frac{x_2centerdot y_1}{2}+frac{x_2centerdot y_2}{2}-frac{x_1centerdot y_2}{2}+frac{x_1centerdot y_1}{2} \ =x_2*y_1-frac{x_2centerdot y_1+x_1 centerdot y_2}{2} \ =|frac{x_2centerdot y_1-x_1centerdot y_2}{2}| ]

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

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

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

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

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

    判交

    可以用点积+叉积判交。

    考虑下面两种情况:

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

    转角

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

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

    极角

    考虑怎么算上面那一个(eta),直接(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
    %.10lf %.10lf
    ",O.r,O.o.x,O.o.y);
    }
    

    自适应Simpson法

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

  • 相关阅读:
    缺省源
    MySQL曹操外卖一
    MySQL曹操外卖二
    正确使用MySQL外键约束
    html大部分实用标签(结构型)
    html超级基础标签
    我的简单作业
    章节课程复习笔记
    FC超级玛丽研究(NES游戏)
    二维码生成
  • 原文地址:https://www.cnblogs.com/mleautomaton/p/10289973.html
Copyright © 2020-2023  润新知