在处理旋转矩形时,两种方法实际上是等效的,只是计算顺序不同。下面是两种方法的详细说明:
1. 旋转并平移到中心点
这种方法的步骤如下:
-
定义矩形的相对角点: 以矩形的中心为原点,定义矩形四个角点相对于中心点的位置。例如:
std::vector<Point> cornersRel{ { -expandedWidth / 2, -expandedHeight / 2 }, { expandedWidth / 2, -expandedHeight / 2 }, { expandedWidth / 2, expandedHeight / 2 }, { -expandedWidth / 2, expandedHeight / 2 } };
-
旋转这些相对角点: 使用旋转矩阵将这些相对角点旋转到所需的角度。
for (size_t i = 0; i < corners.size(); ++i) { corners[i] = rotatePoint(cornersRel[i], cosTheta, sinTheta); }
-
平移到实际中心点: 将旋转后的角点平移到实际的中心点位置。
for (size_t i = 0; i < corners.size(); ++i) { corners[i].x += center.x; corners[i].y += center.y; }
2. 先平移到中心点,再旋转
这种方法的步骤如下:
-
平移到中心点: 先将矩形四个角点平移到中心点位置。
std::vector<Point> corners{ { center.x - expandedWidth / 2, center.y - expandedHeight / 2 }, { center.x + expandedWidth / 2, center.y - expandedHeight / 2 }, { center.x + expandedWidth / 2, center.y + expandedHeight / 2 }, { center.x - expandedWidth / 2, center.y + expandedHeight / 2 } };
-
旋转这些角点: 使用旋转矩阵将这些角点旋转到所需的角度。
for (size_t i = 0; i < corners.size(); ++i) { corners[i] = rotatePoint(corners[i], cosTheta, sinTheta); }
等效性分析
在数学上,这两种方法是等效的。旋转和位移(平移)是线性变换,可以独立应用:
- 平移: 先将所有点移动到所需的位置(中心点)。
- 旋转: 再对这些点应用旋转变换。
旋转矩阵和位移的顺序不会影响最终的结果,只要它们的应用是连贯的。这是因为旋转和位移在数学上可以分开进行,结果是一样的。
代码示例
旋转并平移到中心点
std::vector<Point> cornersRel{
{ -expandedWidth / 2, -expandedHeight / 2 },
{ expandedWidth / 2, -expandedHeight / 2 },
{ expandedWidth / 2, expandedHeight / 2 },
{ -expandedWidth / 2, expandedHeight / 2 }
};
for (size_t i = 0; i < corners.size(); ++i) {
corners[i] = rotatePoint(cornersRel[i], cosTheta, sinTheta);
corners[i].x += center.x;
corners[i].y += center.y;
}
先平移到中心点,再旋转
std::vector<Point> corners{
{ center.x - expandedWidth / 2, center.y - expandedHeight / 2 },
{ center.x + expandedWidth / 2, center.y - expandedHeight / 2 },
{ center.x + expandedWidth / 2, center.y + expandedHeight / 2 },
{ center.x - expandedWidth / 2, center.y + expandedHeight / 2 }
};
for (size_t i = 0; i < corners.size(); ++i) {
corners[i] = rotatePoint(corners[i], cosTheta, sinTheta);
}
两种方法在结果上是一样的,取决于你选择哪个顺序来实现旋转和位移。在实际编程中,选择哪种方式通常取决于个人习惯和代码的清晰度。
==================================================
可以把中心点看作为一个偏移,看作基于原点的偏移。而计算出的距离值是基于原点的坐标,也称为是长度。所以将长度看为基于原点的坐标,对这个坐标进行旋转,然后再加上原点对于中心点的偏移,就是对于中心点的旋转包围框了。