旋转矩阵 - C++

题目描述

任意输入两个9阶以下矩阵,要求判断第二个是否是第一个的旋转矩阵,如果是,输出旋转角度(0、90、180、270),如果不是,输出-1。 要求先输入矩阵阶数,然后输入两个矩阵,每行两个数之间可以用任意个空格分隔。行之间用回车分隔,两个矩阵间用任意的回车分隔。

输入描述:

输入有多组数据。
每组数据第一行输入n(1<=n<=9),从第二行开始输入两个n阶矩阵。

输出描述:

判断第二个是否是第一个的旋转矩阵,如果是,输出旋转角度(0、90、180、270),如果不是,输出-1。
如果旋转角度的结果有多个,则输出最小的那个。

示例1

输入

3
1 2 3
4 5 6
7 8 9
7 4 1
8 5 2
9 6 3

输出

90

分析

不要看到旋转矩阵就懵了,它没有那么复杂的求任意角度的旋转矩阵,只是0 90 180 270 四种,方方正正的矩阵旋转方方正正的角度而已。这样就只是找旋转前后坐标间的关系,就非常简单了,这题没说清楚是按顺时针旋转,否则的话应该不存在270这一答案

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>

using namespace std;
int mat1[11][11], mat2[11][11];

int main()
{
    int n;
    while (cin>>n)
    {
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                scanf("%d", &mat1[i][j]);
        bool flag = true;
        int angle = -1;
        // if 0
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
            {
                scanf("%d", &mat2[i][j]);
                if (mat2[i][j] != mat1[i][j])flag = false;
            }
        if (flag == true)angle = 0;
        else {
        //if 90
            flag = true;
            for(int i = 0;i<n;i++)
                for (int j = 0; j < n; j++)
                {
                    if (mat1[i][j] != mat2[j][n - 1 - i]) { flag = false; break; }
                }
            if (flag == true) angle = 90;
            else {
            //if 270 
                flag = true;
                for (int i = 0; i<n; i++)
                    for (int j = 0; j < n; j++)
                    {
                        if (mat1[i][j] != mat2[n-1-j][i]) { flag = false; break; }
                    }
                if (flag == true)angle = 270;
                else {
                //if 180 
                    flag = true;
                    for (int i = 0; i<n; i++)
                        for (int j = 0; j < n; j++)
                        {
                            if (mat1[i][j] != mat2[n - 1 - i][n-1-j]) { flag = false; break; }
                        }
                    if (flag == true)angle = 180;
                    else {
                        angle = -1;
                    }
                }
            }
        }

        printf("%d\n", angle);

    }
}
以下是将旋转矩阵转换为欧拉角的 C++ 实现代码示例: ### 旋转矩阵转欧拉角实现 ```cpp #include <opencv2/core.hpp> #include <cmath> using namespace cv; // 检查是否为有效的旋转矩阵 bool isRotationMatrix(const Mat &R) { Mat Rt; transpose(R, Rt); Mat shouldBeIdentity = Rt * R; Mat I = Mat::eye(3, 3, shouldBeIdentity.type()); return norm(I, shouldBeIdentity) < 1e-6; } // 将旋转矩阵转换为欧拉角 Vec3f rotationMatrixToEulerAngles(const Mat &R) { assert(isRotationMatrix(R)); double sy = sqrt(pow(R.at<double>(0, 0), 2) + pow(R.at<double>(1, 0), 2)); bool singular = sy < 1e-6; // 奇异情况判断 float x, y, z; if (!singular) { x = atan2(R.at<double>(2, 1), R.at<double>(2, 2)); // 绕 X 轴的角度 y = atan2(-R.at<double>(2, 0), sy); // 绕 Y 轴的角度 z = atan2(R.at<double>(1, 0), R.at<double>(0, 0)); // 绕 Z 轴的角度 } else { x = atan2(-R.at<double>(1, 2), R.at<double>(1, 1)); // 奇异情况下绕 X 轴的角度 y = atan2(-R.at<double>(2, 0), sy); // 奇异情况下绕 Y 轴的角度 z = 0; // 奇异情况下绕 Z 轴角度设为零 } return Vec3f(x, y, z); } ``` 此代码实现了从旋转矩阵到欧拉角的转换逻辑。其中 `isRotationMatrix` 函数用于验证输入矩阵是否是一个合法的旋转矩阵[^1]。 --- ### 使用说明 1. 输入参数为一个 \(3 \times 3\) 的旋转矩阵 `Mat R`。 2. 输出为一个包含三个浮点数值的向量 `Vec3f`,分别对应绕 X、Y 和 Z 轴的旋转角度(单位为弧度)。 3. 如果检测到奇异情况(即旋转矩阵接近奇异性),则会采用特殊处理方式来计算欧拉角[^1]。 --- ### 注意事项 - 此算法假设输入的是标准的旋转矩阵,并且满足正交性和行列式等于 1 的条件。如果输入不满足这些条件,则可能导致错误的结果。 - 返回的欧拉角顺序可能因具体应用需求不同而有所差异,在某些场景下需调整返回值的排列次序[^2]。 --- #### 示例调用 ```cpp int main() { // 定义一个旋转矩阵 Mat R = (Mat_<double>(3, 3) << 0.866, -0.5, 0, 0.5, 0.866, 0, 0, 0, 1); // 调用函数获取欧拉角 Vec3f euler_angles = rotationMatrixToEulerAngles(R); std::cout << "Euler Angles: (" << euler_angles[0] << ", " << euler_angles[1] << ", " << euler_angles[2] << ")" << std::endl; return 0; } ``` 运行以上程序后,将会输出对应的欧拉角值。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值