几何算法面试准备(1)

3D数学相关

本博客内容来源于:https://www.nowcoder.com/discuss/353159115046330368?sourceSSR=search 中的面试问题,感谢KujouAika大佬。

给定点集求凸包

凸包(Convex Hull)是一个计算几何(图形学)中的概念。

在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。

X的凸包可以用X内所有点(X1,…Xn)的线性组合来构造.

在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。

用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点。

例子:假设平面上有p0~p12共13个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来。当这个多边形是凸多边形的时候,我们就叫它“凸包”。如下图:

在这里插入图片描述

1. 把所有点放在二维坐标系中,则纵坐标最小的点一定是凸包上的点,如图中的P0。
2. 把所有点的坐标平移一下,使 P0 作为原点,如上图。
3. 计算各个点相对于 P0 的幅角 α ,按从小到大的顺序对各个点排序。当 α 相同时,距离 P0 比较近的排在前面。例如上图得到的结果为 P1,P2,P3,P4,P5,P6,P7,P8。我们由几何知识可以知道,结果中第一个点 P1 和最后一个点 P8 一定是凸包上的点。 
4. 连接P0和栈顶的那个点,得到直线 L 。看当前点是在直线 L 的右边还是左边。如果在直线的右边就执行步骤5;如果在直线上,或者在直线的左边就执行步骤6。
5. 如果在右边,则栈顶的那个元素不是凸包上的点,把栈顶元素出栈。执行步骤4。
6. 当前点是凸包上的点,把它压入栈,执行步骤7。
7. 检查当前的点 P2 是不是步骤3那个结果的最后一个元素。是最后一个元素的话就结束。如果不是的话就把 P2 后面那个点做当前点,返回步骤4。

原文地址

向量点乘和叉乘的几何意义

向量的点乘:a * b
公式:a * b = |a| * |b| * cosθ
点乘又叫向量的内积、数量积,是一个向量和它在另一个向量上的投影的长度的乘积;是标量。
点乘反映着两个向量的“相似度”,两个向量越“相似”,它们的点乘越大
向量的叉乘:a ∧ b
a ∧ b = |a| * |b| * sinθ
向量积被定义为:
模长:(在这里θ表示两向量之间的夹角(共起点的前提下)(0° ≤ θ ≤ 180°),它位于这两个矢量所定义的平面上。)
方向:a向量与b向量的向量积的方向与这两个向量所在平面垂直,且遵守右手定则。(一个简单的确定满足“右手定则”的结果向量的方向的方法是这样的:若坐标系是满足右手定则的,当右手的四指从a以不超过180度的转角转向b时,竖起的大拇指指向是c的方向。c = a ∧ b)

原文链接

如何判断点在三角形内?

  1. 内角和法
连接点P和三角形的三个顶点得到三条线段PA,PB和PC,求出这三条线段与三角形各边的夹角,
如果所有夹角之和为180度,那么点P在三角形内,否则不在,此法直观,但效率低下。

在这里插入图片描述
2. 同向法

假设点P位于三角形内,会有这样一个规律,当我们沿着ABCA的方向在三条边上行走时,
你会发现点P始终位于边AB,BC和CA的右侧。我们就利用这一点,但是如何判断一个点在线段的左侧还是右侧呢?
我们可以从另一个角度来思考,当选定线段AB时,点C位于AB的右侧,同理选定BC时,
点A位于BC的右侧,最后选定CA时,点B位于CA的右侧,所以当选择某一条边时,
我们只需验证点P与该边所对的点在同一侧即可。问题又来了,如何判断两个点在某条线段的同一侧呢?
可以通过叉积来实现,连接PA,将PA和AB做叉积,再将CA和AB做叉积,
如果两个叉积的结果方向一致,那么两个点在同一测。
判断两个向量的是否同向可以用点积实现,如果点积大于0,则两向量夹角是锐角,否则是钝角。

在这里插入图片描述
3. 重心法

三角形的三个点在同一个平面上,如果选中其中一个点,其他两个点不过是相对该点的位移而已,
比如选择点A作为起点,那么点B相当于在AB方向移动一段距离得到,而点C相当于在AC方向移动一段距离得到。
所以对于平面内任意一点,都可以由如下方程来表示
P = A +  u * (C – A) + v * (B - A) // 方程1
如果系数u或v为负值,那么相当于朝相反的方向移动,即BA或CA方向。
那么如果想让P位于三角形ABC内部,u和v必须满足什么条件呢?有如下三个条件
u >= 0
v >= 0
u + v <= 1

在这里插入图片描述

原文地址

如何判断点在矩形内

在这里插入图片描述
原文地址

如何判断一个多边形是凸多边形

1)角度法:
判断每个顶点所对应的内角是否小于180度,如果小于180度,则是凸的,如果大于180度,则是凹多边形。
2)凸包法:
这种方法首先计算这个多边形的凸包,关于凸包的定义在此不再赘述,首先可以肯定的是凸包肯定是一个凸多边形。如果计算出来的凸多边形和原始多边形的点数一样多,那就说明此多边形时凸多边形,否则就是凹多边形。
3)顶点凹凸性法
利用以当前顶点为中心的矢量叉乘或者计算三角形的有符号面积判断多边形的方向以及当前顶点的凹凸性。
假设当前连续的三个顶点分别是P1,P2,P3。计算向量P1P2,P2P3的叉乘,也可以计算三角形P1P2P3的面积,得到的结果如果大于0,则表示P3点在线段P1和P2的左侧,多边形的顶点是逆时针序列。然后依次计算下一个前后所组成向量的叉乘,如果在计算时,出现负值,则此多边形时凹多边形,如果所有顶点计算完毕,其结果都是大于0,则多边形时凸多边形。
4)辛普森面积法
利用待判别的顶点以及前后两个顶点所组成的三角形,利用辛普森公式计算其面积,如果此三角形面积与整个多边形面积符号相同,那么这个顶点是凸的;如果此三角形面积与整个多边形面积符号不同,那么这个顶点是凹的,即整个多边形也是凹多边形。

原文链接

叉乘求多边形面积

二维向量叉乘得到的是对应平行四边形的有向面积,所以,只要保证按照逆时针对点排序,以下的算法都是可行的:
①凸多边形,选取一个A0,从A1开始依次挑选相邻的两个点,求三角形面积,求和即可
②非凸多边形,同上法,由于算的是有向面积,正负抵消就可以得到面积
③任意多边形,选取其边外一点A0,同上法,答案亦相同

空间两直线求距离

空间两直线之间的位置关系主要可以分为: 重合, 平行, 相交, 异面。
异面:首先将直线方程化为对称式,得到其方向向量n1=(a1,b1,c1),n2=(a2,b2,c2).
	  再将两向量叉乘得到其公垂向量N=(x,y,z),在两直线上分别选取点A,B(任意),得到向量AB,
      求向量AB在向量N方向的投影即为两异面直线间的距离了(就是最短距离啦)
	  最短距离的求法:d=|向量N*向量AB|/|向量N|(上面是两向量的数量积,下面是取模)。
平行:两平行直线
	  L1:(x-x1)/m=(y-y1)/n=(z-z1)/p,L2:(x-x2)/m=(y-y2)/n=(z-z2)/p,
	  记 M1(x1,y1,z1),M2(x2,y2,z2),直线方向向量 s = {m,n,p}
	  则 记向量 M1M2 = {x2-x1,y2-y1,z2-z1} = {a,b,c}
	  故得平行线间的距离
	  d = | M1M2×s | / |s|=√[(bp-cn)^2+(cm-ap)^2+(an-bm)^2]/√(m^2+n^2+p^2)

空间点到空间三角形的最近距离

平面定义:空间中的一点P与法线n,所有在该平面上的点 X 都满足:
n⋅(X−P)=0
求解:空间中的点 Q到平面的最近点:
1. 使用点 Q减去点 P,然后与平面的法线进行 Dot点积运算,求出了点到平面的距离 t。
2. 利用点 Q减去 t 乘于法线 n,则求出了平面上的点 R。

什么是齐次坐标?

齐次坐标能做什么?它是怎么去区分是一个位置,还是一个方向?为什么使用齐次坐标,它有什么好处?

原因:在欧氏几何空间,同一平面的两条平行线不能相交。然而,在透视空间里面,两条平行线可以相交。
笛卡尔坐标系下(1,2)的齐次坐标可以表示为(1,2,1),如果点(1,2)移动到无限远处,在笛卡尔坐标下它变为
(∞,∞),然后它的齐次坐标表示为(1,2,0),因为(1/0, 2/0) = (∞,∞),
为什么叫齐次坐标?
我们把齐次坐标转化为笛卡尔坐标的方法是前面n-1个坐标分量分别除以最后一个分量即可。
齐次坐标好处:齐次坐标可以表示无穷远处的点, 更简洁的表达欧氏空间变换,能够区分一个向量和一个点。
(1)从普通坐标转换成齐次坐标时
如果(x,y,z)是个点,则变为(x,y,z,1);
如果(x,y,z)是个向量,则变为(x,y,z,0)
(2)从齐次坐标转换成普通坐标时
如果是(x,y,z,1),则知道它是个点,变成(x,y,z);
如果是(x,y,z,0),则知道它是个向量,仍然变成(x,y,z)

M矩阵

Model matrix
View martirx
Projection martrix
本质上是一个变换矩阵,用来把一个世界坐标系中的点转换到Clipping space。
当然,如果学过OpenGL的人都知道,3D物体从建模到最终显示到屏幕上面要经历以下几个阶段:
对象空间(Object Space)-世界空间(World Space)-照相机空间(Camera Space/Eye Space)
-裁剪空间(Clipping Space)-设备空间(normalized device space)-视口空间(Viewport)
在OpenGL中,通常的矩阵堆栈操作顺序为先对投影矩阵(P矩阵)进行初始化和操作,
再对视图矩阵(V矩阵)进行初始化和操作,最后对模型矩阵(M矩阵)进行初始化和操作。

如何理解特征值和特征向量?

特征值对应的特征向量就是理想中想取得正确的坐标轴,而特征值就等于数据在旋转之后的坐标上对应维度上的方差。
直接求出矩阵A的特征向量得出对应的特征向量。我们就能找到旋转后正确的坐标轴。
这个就是特征值和特征向量的一个实际应用:“得出使数据在各个维度区分度达到最大的坐标轴。"

SVD

如何表示一个平面?

截距式
设平面方程为Ax+By+Cz+D=0,若D不等于0,取a=-D/A,b=-D/B,c=-D/C,则得平面的截距式方程:x/a+y/b+z/c=1
它与三坐标轴的交点分别为P(a,0,0),Q(0,b,0),R(0,0,c),其中,a,b,c依次称为该平面在x,y,z轴上的截距。

点法式
n为平面的法向量,n=(A,B,C),M,M’为平面上任意两点,则有n·MM’=0, MM’=(x-x0,y-y0,z-z0),
从而得平面的点法式方程:A(x-x0)+B(y-y0)+C(z-z0)=0

一般式
Ax+By+Cz+d=0

最小二乘法

在这里插入图片描述

最小二乘法(又称最小平方法)是一种数学优化技术。
它通过最小化误差(真实目标对象与拟合目标对象的差)的平方和寻找数据的最佳函数匹配。
利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小

Ceres库

四元数和欧拉角优缺点

欧拉旋转:欧拉角Eulerian angles用来确定定点转动刚体位置的3个一组独立角参量,由章动角 θ、旋进角(即进动角)ψ和自转角j组成。
优点:
       很容易理解,形象直观;表示更方便,只需要3个值(分别对应x、y、z轴的旋转角度);
       但按我的理解,它还是转换到了3个3*3的矩阵做变换,效率不如四元数;
缺点:
     之前提到过这种方法是要按照一个固定的坐标轴的顺序旋转的,因此不同的顺序会造成不同的结果;
     会造成万向节锁(Gimbal Lock)的现象。这种现象的发生就是由于上述固定坐标轴旋转顺序造成的。
     理论上,欧拉旋转可以靠这种顺序让一个物体指到任何一个想要的方向,
     但如果在旋转中不幸让某些坐标轴重合了就会发生万向节锁,这时就会丢失一个方向上的旋转能力,
     也就是说在这种状态下我们无论怎么旋转(当然还是要原先的顺序)都不可能得到某些想要的旋转效果,
     除非我们打破原先的旋转顺序或者同时旋转3个坐标轴。这里有个视频可以直观的理解下;
     由于万向节锁的存在,欧拉旋转无法实现球面平滑插值;
四元数:这就表示绕着一个轴(a,b,c)(它是个单位向量)旋转θ \thetaθ角度。
优点:
 可以避免万向节锁现象;
 只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;
 可以提供平滑插值;
缺点:
    比欧拉旋转稍微复杂了一点点,因为多了一个维度;
    理解更困难,不直观;
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值