在 C++ 中,向量类型通常由库提供。C++ 标准库中的 <vector> 头文件提供了一个向量容器 std::vector,但它并不是数学意义上的向量类型,而是一种可变大小的数组容器。如果要使用数学意义上的向量类型,可以使用一些常用的数学库,例如:

GLM(OpenGL Mathematics):是一个专门用于 OpenGL 开发的数学库,提供了矩阵、向量、四元数等数学类型,支持常见的数学运算和变换。

Eigen:是一个用于线性代数计算的 C++ 模板库,提供了矩阵、向量、四元数等数学类型,支持高效的数学计算和线性代数运算。

Boost.Geometry:是 Boost 库中的一个几何库,提供了向量、点、线段、射线等几何类型,支持各种几何运算和算法。

这些库都需要在代码中引用相应的头文件和库文件,具体的引用方式和编译方式可能有所不同,需要根据具体的库文档进行设置和配置。

Eigen官方网站:

http://eigen.tuxfamily.org/index.php?title=Main_Page

在VS2017中使用Eigen的两种方式:

  1. https://blog.csdn.net/weixin_45590473/article/details/122857933

  1. https://blog.csdn.net/weixin_42655134/article/details/107414089

通过以下案例,体会Eigen库在C++中的应用

1、在C++中,使用Eigen模板库,用空间中的三个点建立一个新坐标系,通过转移矩阵计算这三个点在新坐标系中的坐标?

思路如下:

a、通过这三个点计算新坐标系的三个轴向量

b、新坐标系的三个轴向量构成的矩阵求逆可以得到转移矩阵

c、用转移矩阵计算新坐标系下点的坐标。

1.1、为什么新坐标系下三个轴向量求逆就是转移矩阵?

在三维空间中,一个坐标系可以由三个不共线的向量构成,分别代表该坐标系的三个轴。对于一个从旧坐标系变换到新坐标系的变换矩阵,我们可以将其表示为一个3x3的矩阵,其中每一列代表新坐标系的一个轴向量在旧坐标系下的坐标表示。

假设我们已经确定了新坐标系的三个轴向量x_axis_new、y_axis_new和z_axis_new,那么我们就可以将它们构成一个3x3的矩阵,记作rotation,即:

Eigen::Matrix3d rotation;
rotation << x_axis_new, y_axis_new, z_axis_new;

由于rotation的每一列都代表新坐标系的一个轴向量在旧坐标系下的坐标表示,因此rotation的逆矩阵就代表了旧坐标系的三个轴向量在新坐标系下的坐标表示。这样,我们就可以将一个向量从旧坐标系变换到新坐标系中,方法是将这个向量表示为一个列向量,然后乘以rotation的逆矩阵,即:

Eigen::Vector3d v_old(x_old, y_old, z_old);
Eigen::Vector3d v_new = rotation.inverse() * v_old;

因此,我们可以使用rotation的逆矩阵作为转移矩阵,将向量从旧坐标系变换到新坐标系中。

1.2、求原坐标系中的点在新坐标系下的坐标,应该用哪种方式?

(1)、求原坐标系中的点在新坐标系下的坐标,可以使用以下两种方式实现:

使用solve()函数:这种方式将新坐标系的三个轴向量作为矩阵的列向量,将原始坐标系中的点作为向量b,解决线性方程组Ax=b,其中x就是点在新坐标系中的坐标。具体地,代码如下:

Eigen::Matrix3d transMat;
transMat.col(0) = axis1_new;
transMat.col(1) = axis2_new;
transMat.col(2) = axis3_new;
Eigen::Vector3d p_old; // 原始坐标系中的点
Eigen::Vector3d origin; // 新坐标系的原点
Eigen::Vector3d p_new = transMat.solve(p_old - origin);

(2)、使用矩阵乘法:这种方式使用一个4x4的变换矩阵T来表示坐标变换,其中前三行表示新坐标系的三个轴向量,最后一行表示新坐标系的原点。将原始坐标系中的点作为一个4维齐次坐标表示,通过矩阵乘法计算得到点在新坐标系中的4维齐次坐标,然后将齐次坐标除以第四个分量得到点在新坐标系中的三维坐标。具体地,代码如下:

Eigen::Matrix4d transform;
transform << axis1_new, 0,axis2_new, 0,axis3_new, 0,origin_new, 1;
Eigen::Vector4d p_old_homog(p_old(0), p_old(1), p_old(2), 1);
Eigen::Vector4d p_new_homog = transform * p_old_homog;
Eigen::Vector3d p_new = p_new_homog.head<3>() / p_new_homog(3);

这两种方式本质上是等价的,但是实现方式略有不同。使用solve()函数更加直观,但是需要显式地解决线性方程组,可能更加耗时。使用矩阵乘法的方式可能更加高效,但需要注意实现中的齐次坐标转换。具体实现方式应根据具体情况选择。

方式(2)中的思路和思路来源参考2中的代码类似

1.3

Eigen::Vector3d newP2 = transMat.solve(p2 - origin);solve函数的使用和下面这句代码有什么不同吗Eigen::Vector3d p2_new = transform * (p2_old - origin_new);

在Eigen中,solve()函数和使用矩阵乘法都可以用于计算一个向量相对于某个新坐标系的坐标。但是,它们的实现方式有所不同。

solve()函数用于解决线性方程组Ax=b,其中A是一个矩阵,b是一个向量,x是一个未知向量,用于计算向量x的值。在Eigen中,solve()函数的调用格式为x = A.solve(b)。

在这个问题中,我们可以将转移矩阵transMat看作是一个线性变换,它将原始坐标系中的向量变换为新坐标系中的向量。那么,如果我们想要计算向量p2相对于新坐标系的坐标,我们可以将其表示为线性方程组Ax=b,其中A是转移矩阵,b是原始向量p2,x是新坐标系中的向量p2_new。因此,我们可以使用solve()函数来计算p2_new的值,如下所示:

Eigen::Vector3d p2_new = transMat.solve(p2 - origin);

另一方面,矩阵乘法可以将一个向量映射到另一个向量,这是另一种实现向量变换的方法。在Eigen中,我们可以使用矩阵乘法来计算一个向量相对于某个新坐标系的坐标。具体地,我们可以使用一个矩阵transform来表示坐标变换,使用向量p2_old来表示原始坐标系中的向量,使用向量origin_new来表示新坐标系的原点。那么,我们可以使用以下代码来计算p2_new的值:

Eigen::Vector3d p2_new = transform * (p2_old - origin_new);

总体上说,solve()函数和矩阵乘法都可以用于计算向量相对于某个新坐标系的坐标,但它们的实现方式有所不同。solve()函数用于解决线性方程组,而矩阵乘法则将向量映射到新坐标系中。在实践中,使用哪种方法取决于具体的应用场景和需求。

1.4、思路来源参考

  1. https://stackoverflow.com/questions/49769459/convert-points-on-a-3d-plane-to-2d-coordinates/49771112#49771112

  1. https://stackoverflow.com/questions/68506084/i-have-a-plane-between-3-points-and-want-to-get-a-transformation-matrix-which-al

  1. https://stackoverflow.com/questions/52154004/problem-superimposing-and-aligning-3d-triangles/52163563#52163563

  1. https://math.stackexchange.com/questions/1983054/using-3-points-create-new-coordinate-system-and-create-array-of-points-on-xy

1.5、右手定则确定空间坐标系

http://www.gaosan.com/gaokao/262408.html

2、代码实践

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;using Eigen::Matrix3d;// 三个点的坐标信息
//Vector3d p1(1.0, 2.0, 3.0);
//Vector3d p2(4.0, 5.0, 6.0);
//Vector3d p3(7.0, 8.0, 9.0);Vector3d p1(1.0, 0.0, 0.0);
Vector3d p2(0.0, 1.0, 0.0);
Vector3d p3(0.0, 0.0, 1.0);Vector3d p4(0.5, 0.5, 0.0);int main()
{//求新坐标的三个轴向量Eigen::Matrix3d transMat;transMat.col(0) = (p2 - p1).normalized();std::cout << transMat.col(0) << std::endl;transMat.col(2) = transMat.col(0).cross((p3 - p1)).normalized();std::cout << transMat.col(2) << std::endl;transMat.col(1) = transMat.col(2).cross(transMat.col(0));std::cout << transMat.col(1) << std::endl;//求转移矩阵,新坐标的三个轴向量求逆就是转移矩阵Eigen::Matrix3d transform1 = transMat.inverse();//求点在新坐标系下的坐标Eigen::Vector3d origin = p1;Eigen::Vector3d newP1 = Eigen::Vector3d::Zero();Eigen::Vector3d newP2 = transform1 * (p2 - origin);Eigen::Vector3d newP3 = transform1 * (p3 - origin);Eigen::Vector3d newP4 = transform1 * (p4 - origin);std::cout << newP1 << std::endl;std::cout << newP2 << std::endl;std::cout << newP3 << std::endl;std::cout << newP4 << std::endl;}

3、经验证,该代码可以求出原坐标系中的点在新坐标系下的坐标。

VS2017使用Eigen库相关推荐

  1. 使用 Eigen 库写第一个程序

    一.使用 Eigen 库时编译器设置 使用 Eigen 库之前需要下载库文件,并进行简单的设置. 下载地址: http://eigen.tuxfamily.org/index.php?title=Ma ...

  2. ROS中使用Eigen库[不定期更新]

    前期说明 ROS中的数据操作需要线性代数,Eigen库是C++中的线性代数计算库. Eigen库独立于ROS,但是在ROS中可以使用. Eigen库可以参见http://eigen.tuxfamily ...

  3. Eigen库对齐问题:declspec(align('16')) 的形参将不被对齐

    一:错误提示:error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned 英文提示:erro ...

  4. eigen库学习笔记(2)

    这里主要整理矩阵运算相关内容.其中备注了与Matlab的命令对比. eigen库的矩阵运算 Eigen 矩阵定义 Eigen 基础使用 Eigen 特殊矩阵生成 Eigen 矩阵分块 Eigen 矩阵 ...

  5. eigen库学习笔记

    #简介 Eigen是有关线性代数(矩阵.向量等)的c++模板库.支持SSE2/3/4, ARM NEON (32-bit and 64-bit), PowerPC AltiVec/VSX (32-bi ...

  6. Linux下添加eigen头文件,移植Eigen库到SylixOS下及使用方法

    1. 开发环境 宿主机:Windows 7 集成开发环境:Real-Evo IDE 3.5.3 虚拟机:Ubuntu 目标机:x86 2. Eigen简介 Eigen是一个提供了线性代数.矩阵.向量操 ...

  7. 0.前言 与 Eigen库的使用整理

    [C++ 基于Eigen库实现CRN前向推理] 前言:背景 与 Eigen库的使用整理 前言:(Eigen库使用记录) 第一部分:WavFile.class (实现读取wav/pcm,实现STFT) ...

  8. C++ Eigen 库中旋转向量、旋转矩阵、欧拉角、四元数的定义及互相转换

    今天看师兄写的使用力反馈设备操作机械臂的代码,里边涉及到了Eigen 库中的旋转变换,表征旋转变换的有旋转向量Eigen::AngleAxisd.欧拉角Eigen::Vector3d.旋转矩阵Eige ...

  9. 查看eigen库版本的指令

    在调试代码过程中,发现有个关于eigen库文件调取不到的报错,想查看eigen库有没有安装及版本号是多少,试了几个方法,这个指令可行,如下: gedit /usr/include/eigen3/Eig ...

最新文章

  1. tcp connection setup的实现
  2. iOS学习笔记16-SQLite应用
  3. 网管日志-06.08.18
  4. Kafka:分布式消息队列的抽象模型
  5. ABAP 动态的实现任意表的ALV显示
  6. assubclass_Java类class asSubclass()方法及示例
  7. malloc和calloc的区别
  8. 学习Altas 笔记[js调用重载的方法出错,如何处理]
  9. 数据之美系列5(转载)
  10. 如何删除顽固文件或文件夹?
  11. proj4js 坐标转换
  12. 一直很火的steam汇率差赚钱项目详解,如何月入过万
  13. Android柠檬水面试题,柠檬水的饮料摊(面试案例)
  14. 定量变量和定性变量的转换(Transform of Quantitative Qualitative Variables)
  15. Android之——流量管理程序示例
  16. 执行方案(Command)
  17. 实践|美创助力“云学堂”数据安全风险管控建设
  18. Intel D435深度相机“No Frames Received!“问题
  19. 预计每天全世界上传的短视频超过4亿条
  20. Wandb——Pytorch模型指标可视化及超参搜索

热门文章

  1. 仿陌陌注册登录引导页背景效果
  2. 广州科二化龙考场_广州科目二考试化龙考场考试流程是什么,注意事项是什么...
  3. 1.1.4 图片自动编号
  4. 图论5:Tarjan!塔尖!
  5. android mimi 病毒如何,迷你脑将揭开人类朊病毒的神秘面纱
  6. 鸡蛋的硬度(信息学奥赛一本通)
  7. 罗大佑无愧于我们的青春
  8. java岩浆数码西游记悟空传,西游记悟空传
  9. 图解正向代理、反向代理、透明代理
  10. 【Android】应用数据和文件#存储空间概览