我正在尝试计算通过二维仿射矩阵进行变换的圆的轴对齐边界框,该矩阵可以包含任何操作(平移、旋转、缩放、倾斜)。
我认为最好的方法是用矩阵变换圆并获得旋转的椭圆,但我不知道如何正确执行。到目前为止,我所拥有的是一个可以计算旋转椭圆(未附加)的边界框的代码和一个可以将圆部分转换为椭圆的代码(中心和半径,但缺少椭圆旋转):
transformCircle(in matrix, in circle, out ellipse) {
ellipse.center = matrix * circle.center
// Calculate conjugated half-diameters
f1 = matrix * vec2(circle.radius, 0)
f2 = matrix * vec2(0, circle.radius)
r = f1.x^2 + f1.y^2 + f2.x^2 + f2.y^2
s = cross(f1, f2)
p = sqrt(r + 2*s)
q = sqrt(r - 2*s)
ellipse.radiusX = 0.5 * (p + q)
ellipse.radiusY = 0.5 * (p - q)
ellipse.rotation = ???; // Need help here
}
我的问题是:
感谢@Mike'Pomax'Kamermans 在评论中提供了一些公式的链接,其中的答案之一包含椭圆旋转所需的公式。
为了将来的参考和搜索此内容的人们,将 2D 圆转换为 2D 旋转椭圆的完整伪代码,我将圆与任意 2D 仿射变换矩阵相乘是这样的:
transformCircle(in matrix, in circle, out ellipse) {
ellipse.center = matrix * circle.center
// Calculate conjugated half-diameters
f1 = matrix * vec2(circle.radius, 0)
f2 = matrix * vec2(0, circle.radius)
f1x2 = f1.x^2
f1y2 = f1.y^2
f2x2 = f2.x^2
f2y2 = f2.y^2;
r = f1x2 + f1y2 + f2x2 + f2y2
s = cross(f1, f2)
p = sqrt(r + 2*s)
q = sqrt(r - 2*s)
ellipse.radiusX = 0.5 * (p + q)
ellipse.radiusY = 0.5 * (p - q)
ellipse.rotation = acos((f1x2 + f2x2 - f1y2 - f2y2) / sqrt(r^2 - 4 * s^2)) * 0.5
}