上次说到我打算详细的说一说接触算法,
那么今天就从接触算法的开端,接触搜索开始,今天先来讲一讲箱排序(bucket-sorting)。首先接触搜索一般来说是一个从全局到局部的过程(也就是很多人喜欢说的Global-local),首先我们通过全局的搜索来快速判断几个物体是否相交,然后再局部的定位哪些单元进行了相交。
以最为常见的两个面之间的接触来说,我们首先定义两个面(在有限元中通常称为主面和从面),我们可以非常简单的计算出这两个面的包围盒子(bounding box),这里计算包围盒子的方法也有很多,后续会讲,最简单的那种(AABB)大家就可以理解成从各个方向上的最小值延伸到各个方向的最大值的一个空间六面体。然后如果两个面包围盒子本身都没有接触,我们就不用进行局部的检测了,如果两个面有的话,我们可以选用两个包围盒子相交的部分进行进一步的接触检测,具体如下图所示。
那么进一步我们需要找到的则是哪个单元和哪个单元或者节点发生了接触,存储成接触对的信息进行接下来的计算,这时候我们就可以采用空间箱排序的技术。总的来说其实非常简单,就是对空间画格子,2D空间就是画长方形格子,3D空间画六面体的格子,然后一个格子中的单元(节点)只跟格子中或者相邻格子中的单元或节点进行接触检测,这样呢就避免了距离非常远的单元进行无意义的检测,整体上提升了效率。
如下图所示,如果我们采用传统的点对面的接触算法(NTS),我们的从面节点需要向主面单元进行投影,假设下边的面为从面, 上面的是主面,我们针对三角形的节点,则只需要在该点所在盒子内部与该盒子周边的盒子进行接触检测就行,比如S点只需呀在S点所在的盒子检测,发现没有,然后去周边的盒子检测,发现了边AB。这里是个简单的2D的例子,对于3D的搜索其实是类似的,原理一样,代码也不用多写啥。
由于空间中的点根据设定的x,y,z 三个方向上盒子的尺寸,可以快速的直接定位盒子的ID,然后找到盒子中需要搜索的元素,理论上,在单元分布比较均匀的时候,这个搜索方法是 的,也就是接近于线性的,与之前所说的穷举 形成了鲜明的对比,当然如果你全局就画一个盒子,那么就还是这么糟糕。所以大家也可以看到,单元尺寸、空间的分布及盒子的大小会极大的影响这套算法的效率,那么往往单元的尺寸、空间的分布由用户案例具体问题决定,开发者并不能改变什么,那么盒子的大小就很关键了,研究表明以下的盒子尺寸算是一个最优的
其中 为单元的边长的最大值,这个取值可以保证其只进行1层“邻居盒子”的搜索。具体可以参考我的友人V.A Yastrebov 的博士论文[1]。
这套方法还有一个好处就是他非常简单去构建,去更新,对于大变形分析,只需要简单的更新坐标,更新包围盒子,重新画一下格子,就完事了。这些操作均是非常简单且快速的。还有一点就是因为各个节点也就在自己的盒子和周边的盒子内进行搜索,所以非常容易并行。
今天先说到这,下次接着讲其他的空间搜索相关的知识。
参考文献: