几何算法库中的浮点数误差问题

真正做过工业级图形算法库的人应该都被浮点数误差问题折磨过吧,反正我曾经被这个问题折磨的欲仙欲死。不夸张的说,因为这个问题的存在,几乎所有图形算法都不能完全按书上的实现,哪怕是最简单的判断点内外的射线法,在接近重合以及几何体不完美的情况下也会出错,都需要特殊处理(这个几何体不完美指的是几何体经过若干运算后,本身就带了误差,这个是必然会出现的)。
我曾经主导过某大型软件公司完全自助知识产权的图形平台的核心技术研发,基于这个平台的多个软件也经历了市场的考验,是真刀真枪干过的。随着各种问题的暴露与解决,我对误差的认识也逐渐深刻,下面把现在能想到的关键点和致力于图形算法研发的朋友分享一下,也算是为国产自主可控做点贡献吧。
误差情况太多了,不能一一列举,下面是高度概括后的,可能写的有点抽象和不全面,欢迎大家一起讨论。
浮点数误差的核心问题,一句话概括就是:浮点数误差导致歧义,歧义导致错误。所以,浮点数误差问题的根本解就是歧义检测与歧义处理。
歧义的检测最好的方式就是利用几何的拓扑关系,例如相交的穿过关系,点线面的连接关系等,这些检测往往不需要大量额外计算,一般采用原有计算中的副产品即可。
歧义的发生情况很多,需要不断的积累,常见的原因概括如下:
1、不同含义的容差带来的歧义。
例如一般的图形库都会设置距离容差和角度容差,这两个容差有一定的倍率关系。这些误差一般情况下会工作的很好,但在接近重合时,经常会出现一个满足重合要求,另一个不满足。这个歧义的消除,就需要算法都统一到距离误差下,但统一到距离误差下往往会使算法变慢,所以,折中的方案是两个角度误差,一大一小,小于小的绝对重合,大于大的绝对不重合,两者之间的转为距离误差的算法。
2、局部运算带来的歧义。
例如两个体求交,要先一个面一个面的求交,为讨论方便,简化成一条折线和一条直线相交。如果折线的折点到直线的距离在误差范围内,折线的一条边和直线无完美交点,另一条边有一个不在端点的完美交点歧义就发生了,因为端点在误差范围内,所以无完美交点的边会把端点当成交点(不太方便画图,大家脑补吧)。这时候歧义就发生了,本来应该一个交点的出来了两个。这种歧义的检测可以通过相交计数,交点不在端点的计数加2,端点的加1,然后通过分析计数的奇偶发现歧义。解决方法要不删除歧义点,要不把有交点的与直线处理成局部重合。
3、多次运算后几何体变得并不完美。
这里的不完美指的是几何体两条相邻边的端点存在一个满足精度误差,或两个面的相邻边和面存在误差。通过修复强行消除这些误差,要么修复算法本身很慢,要么有可能会引入局部自交。对于这种情况,有些算法库会在顶点、边等对象中加入一个当前容差。我认为解决这个问题的最好办法还是利用拓扑关系检测,根据检测结果对计算结果修正或指导重新运算。如果想简单点,就是检测并加入一个小的扰动跳出误差影响范围。
4、代数解法造成的误差不统一。
在处理曲线曲面求交等运算时,需要将运算转为非线性方程组求解问题,这时候重要的是找到方程组以及求解过程中各结果的几何意义,这样才能使求解误差和我们设置的距离误差统一到同一体系下,否则在后续计算结果应用中,极端情况下出问题的概率将大大提升。
总之,在几何算法实现中,脑子里要时刻想着浮点数误差的存在,怀疑一切,并让它成为自己的思维习惯。
 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值