首页/文章/ 详情

有限元基础知识:AABB包围盒的计算

1月前浏览612

上次说了接触计算中的几种不同的包围盒子,有限元基础知识:接触计算中的包围盒子

下面开始分别讲一下各自的编码实现,先从最简单的AABB开始,AABB包围盒由于每个面(3D)都与坐标系平行,所以其实只需要找到,x,y,z 三个方向上所有节点的最大值和最小值就行了。

下边以C++代码为例,给大家示范一下AABB的计算流程

// 函数定义
using point3D = std::array<double3>;

struct AABB
{

 point3D min;
 point3D max;
 
 void init();
 void addPoint(const point3D & p)
}
;

void AABB::init()
{
 min[0] = min[1] = min[2] = FLT_MAX;
 max[0] = max[1] = max[2] = -FLT_MAX;
};

void addPoint(const point3D & p)
{
    if (p[0] < min[0]) min[0] = p[0];
    if (p[0] > max[0]) max[0] = p[0];
    if (p[1] < min[1]) min[1] = p[1];
    if (p[1] > max[1]) max[1] = p[1];
    if (p[2] < min[2]) min[2] = p[2];
    if (p[2] > max[2]) max[2] = p[2];
};


// 真正的形成一个AABB
AABB box;
box.init();
// 对于主面或者从面的节点循环
// points is a vector of point3D
for (auto p : points)
{
 box.addPoint(p);
}

那么这样一个主面或者从面的包围盒子就形成了,然而在真实的有限元计算中,由于我们需要定位潜在可能发生的接触,或者接触已经发生了,已经有了微小的穿透,以上还需要进行一点点补充,就是增加一些buffer,给现在的box扩大一圈,一般的做法如下:

void AABB::addBuffer(double dis)
{
 min[0] -= dis;
 min[1] -= dis;
 min[2] -= dis;
 max[0] += dis;
 max[1] += dis;
 max[2] += dis;
};

box.addBuffer(dis);

这样我们就完成了一个扩大化的bounding box, 如下图所示,蓝色的就是最开始计算的box,而红色虚线就是加上了buffer的box 

那么然后就是如何检测两个bounding box 是否接触了,这个也非常简单,若所有轴均重叠则碰撞,否则就不

bool AABBIntersect(const AABB & box1, const AABB & box2)
{
 return (box1.min[0] <= box2.max[0] && box1.max[0] >= box2.min[0]) &&
               (box1.min[1] <= box2.max[1] && box1.max[1] >= box2.min[1]) &&
               (box1.min[2] <= box2.max[2] && box.max[2] >= box2.min[2]);
}

这样我们就能检测两个AABB的box是否接触,做一个粗放式的检查。

好了今天就先到这,明天讲一下OBB与分离轴定理SAT的编码实现,敬请期待。


来源:大狗子说数值模拟
碰撞
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2025-05-15
最近编辑:1月前
大狗子说数值模拟
博士 传播国际一流的数值模拟算法
获赞 10粉丝 19文章 62课程 0
点赞
收藏
作者推荐

有限元基础知识:关于接触的事

接触分析在众多有限元分析中是一个比较特殊的领域,大部分有限元算法(教科书上那些)研究连续体内部的应力应变、整体变形等。而接触分析则是研究两个或多个物体(自接触另说)之间的作用关系。另外呢大部分有限元的书,商业软件的理论文档都对接触这里描述的不多。我呢有幸在计算接触力学领域耕耘多年,打算今天先做一个引子,引出未来一步步给大家说的接触分析相关内容。接触搜索接触首先的第一步是要分析两个物体哪里发生接触,这个在显式分析和隐式分析中会有些不同,集中体现在:显式中,已经穿透的就是发生接触的区域隐式中,可能在这步中发生穿透的要检测出来,用于之后的计算但是两者都离不开一个核心诉求,那就是接触搜索(找到发生接触或者潜在发生接触的区域),这个过程呢与其说是个有限元的过程,其实更接近于图形学也就是CG的那些知识。最简单但却不可用的方法,就是穷举,将主面m个单元和从面n个单元所有单元都建立一个接触单元用于后续分析,那么算下来程序内部就会有个接触单元对,耗时耗力,根本不可行。所以为了解决这样的问题,我们就要引出一些技术以快速的进行接触搜索,常见的有:bucketsortingBVH(boundaryvolumehierarchy):通常就是指大家常说的八叉树、k-dtree、binarytree等Postioncode:给每个单元附上一个code,然后通过code去查询单元附近的单元,只在这个范围内搜索总之呢要么就是对空间进行划分,要么就是对单元去进行排序,然后一个原则就是,两个接触面中个接触单元对中大部分真实情况下是绝对不可能接触的,接触检测的时候也没必要去搜索他们,提高效率与降低存储空间。接触有限元计算当搜索完了可能的接触对之后,我们进行局部的一些投影、分割等,进行真正的接触有限元计算部分,也就是说形成一些刚度矩阵、载荷向量,这个过程中,我们主要会有两类方法的区别:点对面面对面这里的两种方法指的是接触的离散方法,并不是说点对面只能用于点和面的接触,其实在用户层面都可以选择两个面进行接触。之前写过这个的文章,可以看:结构仿真小知识:点对面及面对面当选定了这两种方法中的任何一种后,我们都会面临一个问题,那就是如何施加如下的接触约束:由于接触问题之于有限元麻烦的就在于,传统有限元本质上是一个优化问题(求能量最小),而接触分析则是一个约束优化问题(在接触约束的情况下,求能量最小),那么我们就要引入一些方法来实现上述的接触约束,总体上有:罚函数法(penalty)拉格朗日乘子法(LM)增广拉格朗日乘子法(AugmentedLM)内点法以及其他约束优化的方法其实都可以用事情还没结束OK,至此如果你正确、且高效的完成了接触搜索、使用某种离散方式构建了接触的关系,通过某种约束方法写出了其刚度矩阵和载荷向量的贡献,那么理论上你是可以求解一个接触问题的。然而事实往往事与愿违(大部分论文绝对不会说这部分,只有鲜花),我们往往会遇到算法稍微算个复杂点的问题就不收敛、算出来的应力、接触力、支座反力上蹿下跳一点不平稳、过盈配合根本算不了等等问题。当然这些问题都有答案,但涉及很多细节的打磨,比如:针对点对面算法,应力、接触力上窜下跳就可以换面对面算法,还是一股脑的选择点对面呢,就可以用光顺化(Smoothing)技术以去除由于有限元离散造成一些影响,甚至可以采用基于IGA,NURBS的边界描述进行接触分析针对有些高阶单元,并不适合用在接触分析中,提出适合接触分析的高阶单元算法面对面Mortar法实现起来比较麻烦,很多人又提出了各种变形,而对mortar法中各种离散格式也有各种变形为了提高收敛性对penalty系数的自动选择、对分析步步长进行更为细节的自动控制引入多种摩擦本构模型,来更容易更准确的模拟真实情况对于自接触分析增加诸多判断、更快更正确的进行几何搜索对过盈配合施加渐进式过盈配合与自定义曲线等......总的来说接触分析是一个资料特别少、算法基础要求挺高、且条条大路可能都通罗马,但是要在路上自己对付各条路上的盗贼的领域,没有哪条道路一路顺风,我希望在未来给大家详细展开说一说这方面的内容,不求最学术最理论、但求在计算接触力学这个领域最直接、最真实可用。来源:大狗子说数值模拟

未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈