在已知矩形中心点、长宽和旋转角度(定义为矩形最长边与X轴正方向的夹角),如何确定矩形四个顶点的坐标,通常有以下两种处理方法。
法一:直接对顶点进行旋转
比如下图虚线框矩形是实线框矩形绕矩形中心点旋转后得到。在已知矩形中心点坐标和长宽的前提下,实线框四顶点坐标可直接换算得到。然后就是分析计算经旋转后的虚线框矩形的四顶点坐标。

由于是绕矩形中心点旋转,因此可以将坐标系原点平移到矩形中心点位置。然后将矩形框四顶点用极坐标表示,并转换成直角坐标。
 
旋转前A顶点坐标:(其中表示矩形框四个顶点距离坐标原点的距离,α表示顶点与坐标原点连线与X轴的夹角)
则绕坐标原点旋转θ角度后A'顶点坐标:
对A'顶点坐标按照三角函数的和差角公式展开:
将A顶点坐标代入A'顶点坐标则有:
用矩阵形式表示:
由于坐标系原点被平移到矩形中心点位置,因此最终还需将A'顶点坐标平移回去:
法二:根据三角形几何性质换算顶点坐标
针对四顶点分别绘制出下图所示辅助线,通过相似三角形不难得到下图中两相等辅助角。

矩形四顶点坐标分别为:
 
 
由于A与C、B与D分别是关于的对称点,所以各项正负号相反。
C++代码实现
#include <iostream>
#include <cmath>
#include <vector>
// #include <Eigen/Core>
#include <eigen3/Eigen/Core>
#define MATH_PI 3.14159265358979323846264338327950288419716939937510L
template <typename T>
struct Point2D {
  T x = 0;
  T y = 0;
};
typedef Point2D<float> Point2DF;
typedef Point2D<double> Point2DD;
typedef struct {
    Point2DF center;
    float length;
    float width;
    float theta; //rad, (-pi,pi]
} ST_BOX_INFO;
typedef struct {
    Point2DF a;
    Point2DF b;
    Point2DF c;
    Point2DF d;
} ST_BOX_FOUR_VERTICES;
void RotateBoxVerticesMethod1(const ST_BOX_INFO& origin_box, ST_BOX_FOUR_VERTICES& rotated_box);
void RotateBoxVerticesMethod2(const ST_BOX_INFO& origin_box, ST_BOX_FOUR_VERTICES& rotated_box);
int main(void) {
    ST_BOX_INFO origin_box;
    origin_box.center.x = 4;
    origin_box.center.y = 3;
    origin_box.length = 4;
    origin_box.width = 2;
    origin_box.theta = 0.5 * MATH_PI;
    // origin_box.theta = 0.5 * 0.5 * MATH_PI;
    ST_BOX_FOUR_VERTICES rotated_box1, rotated_box2;
    RotateBoxVerticesMethod1(origin_box, rotated_box1);
    RotateBoxVerticesMethod2(origin_box, rotated_box2);
    return 0;
}
void RotateBoxVerticesMethod1(const ST_BOX_INFO& origin_box, ST_BOX_FOUR_VERTICES& rotated_box) {
    Eigen::MatrixXd R = Eigen::MatrixXd::Zero(8, 8);
    Eigen::VectorXd t(8);
    Eigen::VectorXd vertices(8);
    const auto l_half = 0.5 * origin_box.length;
    const auto w_half = 0.5 * origin_box.width;
    auto theta = origin_box.theta;
    if (1.0e-6 > (MATH_PI - std::fabs(theta))) {
        theta = 0.0;
    } else if (1.0e-6 > std::fabs((0.5 * MATH_PI) - std::fabs(theta))) {
        ;
    } else if ((0.5 * MATH_PI) < theta) {
        theta = theta - MATH_PI;
    } else if ((-0.5 * MATH_PI) > theta) {
        theta = theta + MATH_PI;
    }
    rotated_box.a.x = origin_box.center.x + l_half;
    rotated_box.a.y = origin_box.center.y + w_half;
    rotated_box.b.x = origin_box.center.x - l_half;
    rotated_box.b.y = origin_box.center.y + w_half;
    rotated_box.c.x = origin_box.center.x - l_half;
    rotated_box.c.y = origin_box.center.y - w_half;
    rotated_box.d.x = origin_box.center.x + l_half;
    rotated_box.d.y = origin_box.center.y - w_half;
    std::cout << "before rotated: (" << rotated_box.a.x << ',' << rotated_box.a.y << ')'
             << '(' << rotated_box.b.x << ',' << rotated_box.b.y << ')'
             << '(' << rotated_box.c.x << ',' << rotated_box.c.y << ')'
             << '(' << rotated_box.d.x << ',' << rotated_box.d.y << ')' << std::endl;
    R(0, 0) = R(1, 1) = R(2, 2) = R(3, 3) = R(4, 4) = R(5, 5) = R(6, 6) = R(7, 7) = std::cos(theta);
    R(1, 0) = R(3, 2) = R(5, 4) = R(7, 6) = std::sin(theta);
    R(0, 1) = R(2, 3) = R(4, 5) = R(6, 7) = -R(1, 0);
    t << origin_box.center.x, origin_box.center.y, origin_box.center.x, origin_box.center.y,
        origin_box.center.x, origin_box.center.y, origin_box.center.x, origin_box.center.y;
    vertices << rotated_box.a.x, rotated_box.a.y,
                rotated_box.b.x, rotated_box.b.y,
                rotated_box.c.x, rotated_box.c.y,
                rotated_box.d.x, rotated_box.d.y;
    const Eigen::VectorXd rslt = R * (vertices - t) + t;
    rotated_box.a.x = rslt(0);
    rotated_box.a.y = rslt(1);
    rotated_box.b.x = rslt(2);
    rotated_box.b.y = rslt(3);
    rotated_box.c.x = rslt(4);
    rotated_box.c.y = rslt(5);
    rotated_box.d.x = rslt(6);
    rotated_box.d.y = rslt(7);
    std::cout << "after rotated: (" << rotated_box.a.x << ',' << rotated_box.a.y << ')'
             << '(' << rotated_box.b.x << ',' << rotated_box.b.y << ')'
             << '(' << rotated_box.c.x << ',' << rotated_box.c.y << ')'
             << '(' << rotated_box.d.x << ',' << rotated_box.d.y << ')' << std::endl;
}
void RotateBoxVerticesMethod2(const ST_BOX_INFO& origin_box, ST_BOX_FOUR_VERTICES& rotated_box) {
    auto theta = origin_box.theta;
    if (1.0e-6 > (MATH_PI - std::fabs(theta))) {
        theta = 0.0;
    } else if (1.0e-6 > std::fabs((0.5 * MATH_PI) - std::fabs(theta))) {
        ;
    } else if ((0.5 * MATH_PI) < theta) {
        theta = theta - MATH_PI;
    } else if ((-0.5 * MATH_PI) > theta) {
        theta = theta + MATH_PI;
    }
    Eigen::Vector2d direction(std::cos(theta), std::sin(theta));
    Eigen::Vector2d orthog_dir(-direction.y(), direction.x());
    Eigen::Vector2d delta_x = 0.5 * origin_box.length * direction;
    Eigen::Vector2d delta_y = 0.5 * origin_box.width * orthog_dir;
    Eigen::Vector2d center = Eigen::Vector2d(origin_box.center.x, origin_box.center.y);
    std::vector<Eigen::Vector2d> vertices(4);
    vertices[0] = center + (delta_x + delta_y);
    vertices[1] = center + (-delta_x + delta_y);
    vertices[2] = center + (-delta_x - delta_y);
    vertices[3] = center + (delta_x - delta_y);
    
    rotated_box.a.x = vertices[0](0);
    rotated_box.a.y = vertices[0](1);
    rotated_box.b.x = vertices[1](0);
    rotated_box.b.y = vertices[1](1);
    rotated_box.c.x = vertices[2](0);
    rotated_box.c.y = vertices[2](1);
    rotated_box.d.x = vertices[3](0);
    rotated_box.d.y = vertices[3](1);
    std::cout << "after rotated: (" << rotated_box.a.x << ',' << rotated_box.a.y << ')'
             << '(' << rotated_box.b.x << ',' << rotated_box.b.y << ')'
             << '(' << rotated_box.c.x << ',' << rotated_box.c.y << ')'
             << '(' << rotated_box.d.x << ',' << rotated_box.d.y << ')' << std::endl;
}若是要计算三维长方体的的八个顶点(已知中心点、长宽高和旋转角度,且pitch、roll角恒为0°),则用以上同样的方法先计算底部长方形的四顶点坐标,然后再将长方体的高累加到四顶点坐标对应轴上,即可得到顶部长方形四顶点的坐标。
其它方法可在评论区留言补充。


















