对包围框的旋转

在处理旋转矩形时,两种方法实际上是等效的,只是计算顺序不同。下面是两种方法的详细说明:

1. 旋转并平移到中心点

这种方法的步骤如下:

  1. 定义矩形的相对角点: 以矩形的中心为原点,定义矩形四个角点相对于中心点的位置。例如:

    std::vector<Point> cornersRel{
        { -expandedWidth / 2, -expandedHeight / 2 },
        { expandedWidth / 2, -expandedHeight / 2 },
        { expandedWidth / 2, expandedHeight / 2 },
        { -expandedWidth / 2, expandedHeight / 2 }
    };
    
  2. 旋转这些相对角点: 使用旋转矩阵将这些相对角点旋转到所需的角度。

    for (size_t i = 0; i < corners.size(); ++i) {
        corners[i] = rotatePoint(cornersRel[i], cosTheta, sinTheta);
    }
    
  3. 平移到实际中心点: 将旋转后的角点平移到实际的中心点位置。

    for (size_t i = 0; i < corners.size(); ++i) {
        corners[i].x += center.x;
        corners[i].y += center.y;
    }
    

2. 先平移到中心点,再旋转

这种方法的步骤如下:

  1. 平移到中心点: 先将矩形四个角点平移到中心点位置。

    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 }
    };
    
  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);
}

两种方法在结果上是一样的,取决于你选择哪个顺序来实现旋转和位移。在实际编程中,选择哪种方式通常取决于个人习惯和代码的清晰度。

==================================================
可以把中心点看作为一个偏移,看作基于原点的偏移。而计算出的距离值是基于原点的坐标,也称为是长度。所以将长度看为基于原点的坐标,对这个坐标进行旋转,然后再加上原点对于中心点的偏移,就是对于中心点的旋转包围框了。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值