计算几何初步

计算几何学习笔记


向量表示

当然是用点对\((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法

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

转载于:https://www.cnblogs.com/mleautomaton/p/10289973.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值