有没有数值稳定的角平分线算法?
\n\n问题如下:
\n\n实际上我是按以下方式计算的:
\n\n我的方法的问题是,当角度几乎为 180\xc2\xb0(AB 几乎平行于 BC)时,平分线非常不准确(当然是因为中点几乎与 B 重合)。当前的算法非常不准确,有时生成的平分线几乎与其他两条线段之一平行。
\n\n是的,不存在“转换”问题,所有计算都是以单精度浮点完成的。
\n它\xe2\x80\x99并不是微不足道的。让\xe2\x80\x99s 表示两个边缘向量是a 和b:
\n\nfloat2 a = A - B;\nfloat2 b = C - B;\nRun Code Online (Sandbox Code Playgroud)\n\n计算点积float dp = dot( a, b )
标准化两个向量:
float2 a_norm = normalize( a );\nfloat2 b_norm = normalize( b );\nRun Code Online (Sandbox Code Playgroud)\n\n检查点积的符号位。当dp为非负数时,\nreturn normalize( a_norm + b_norm );则\xe2\x80\x99 就完成了。
当点积为负时,输入向量之间存在钝角。\n在这种情况下应用 na\xc3\xafve 公式会降低数值精度。\n需要另一种方法。
float2 c = normalize( a_norm - b_norm );\nfloat dir = dot( a, rotate90( b ) );\nreturn ( dir < 0 ) ? rotate90( c ) : rotate270( c );\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,-而不是+,这才是精度获胜的原因。a当和之间的角度b大于 90\xc2\xb0 时,a和之间的角度-b小于 90\xc2\xb0,且 的长度a_norm - b_norm足以给出准确的方向。之后我们只需将其沿正确的方向旋转 90\xc2\xb0 即可。
PS 将 2D 向量旋转 90\xc2\xb0 的倍数是无损操作。\n这里\xe2\x80\x99s 为rotate90 和rotate270 函数的伪代码:
\n\nfloat2 rotate90( float2 vec )\n{\n return float2( vec.y, -vec.x );\n}\nfloat2 rotate270( float2 vec )\n{\n return float2( -vec.y, vec.x );\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1828 次 |
| 最近记录: |