当前位置: 首页 > news >正文

PCL点云库入门——PCL库中Eigen数学工具库的基本使用(持续更新)

0、前言

        PCL点云库中的算法都基于Eigen数学工具库来实现的,因此,掌握Eigen库对于深入理解和应用PCL点云库至关重要。Eigen库不仅提供了高效的矩阵和向量运算,还支持复杂的线性代数、几何变换等操作,为PCL点云处理提供了强大的数学支持。PCL库中已经包含了Eigen库不需要单独的安装,直接包含头文件就可以使用,因此安装不在讲述。

1、Eigen库的简介

        Eigen库是一个高性能的C++模板库,专注于线性代数、矩阵和向量运算,以及相关的数值分析和算法。

1.1、Eigen库的特性

        Eigen库有如下一些特点:

        1)、易用性

        Eigen库是一个头文件库,这意味着它不需要编译成库文件,也不需要动态链接。开发者只需将Eigen的头文件包含在项目中即可使用,这极大地简化了集成过程。同时,Eigen支持多种数据类型,包括整数、浮点数和复数等,通过模板编程,Eigen能够为这些数据类型提供高效的矩阵和向量运算。

        2)、高性能与优化

        Eigen经过高度优化,能够充分利用现代CPU的性能。它支持SIMD(单指令多数据)指令集,如SSE和AVX,以及多线程计算,从而实现了高效的并行运算。此外,Eigen对稀疏矩阵和密集矩阵都提供了良好的支持,并且针对各种矩阵运算进行了优化,如矩阵乘法、矩阵分解(如Cholesky分解、QR分解、SVD分解)等。

        3)、灵活性与可扩展性

        Eigen库提供了多种矩阵大小选项,包括动态大小和固定大小,以满足不同的应用需求。用户还可以自定义扩展Eigen以适应特殊的数据结构或运算。这种灵活性和可扩展性使得Eigen能够广泛应用于各种领域。    

        4)、应用领域广

        Eigen库被广泛应用于科学计算、机器学习、计算机图形学、计算机视觉、信号处理、金融等领域。在科学计算中,Eigen可以用于求解线性方程组、矩阵分解和特征值问题等。在机器学习和计算机视觉中,Eigen常用于数据降维、模型参数估计、图像特征提取等任务。此外,Eigen还支持常用的几何运算,如旋转矩阵、四元数、矩阵变换等,这使得它在3D计算和机器人学中也具有广泛的应用。

1.2、Eigen库中的主要模块

        Eigen库中的主要模块如下表所示:

功能模块

简要功能描述

Core

包含Matrix和Array类,支持基础的线性代数运算和数组操作。

Geometry

提供旋转、平移、缩放以及2维和3维的各种变换功能。

LU

用于求逆、行列式以及LU分解。

Cholesky

支持LLT和LDLT Cholesky分解。

Householder

提供Householder变换。

SVD

实现奇异值分解(SVD),并配备最小二乘解算器。

QR

实现QR分解,并提供HouseholderQR、ColPivHouseholderQR、FullPivHouseholderQR三种方法。

Eigenvalues

用于特征值和特征向量的分解,提供EigenSolver、SelfAdjointEigenSolver、ComplexEigenSolver等方法

Sparse

支持稀疏矩阵的存储和运算。

Dense

包含Core、Geometry、LU、Cholesky、SVD、QR、Eigenvalues等模块,是Eigen库的核心部????

 2、Eigen库中向量和矩阵的定义

        在Eigen库中,所有的矩阵和向量均被视为矩阵模板类的实例。向量可以被看作是特殊形式的矩阵,具体表现为只包含1行或1列。

2.1、 Eigen库中的矩阵类

        Eigen库中Matrix类包含六个模板参数,目前仅需掌握其前三个参数。余下的三个参数均设有默认值,目前我们不予以深入探讨,后续章节将对此进行详细讨论。

        Matrix的三个必要模板参数为:

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

        其中三个参数的含义如下: 

        Scalar:代表标量类型,即数据类型。换言之,若您需要一个浮点数矩阵,请在此选择float。

常用的还有double和int类型。

        RowsAtCompileTimeColsAtCompileTime:指的是在编译阶段已确定的矩阵行数和列数(若编译时无法确定,可以动态的指定后面进行讨论)。

        Eigen库中提供了许多常用的矩阵类型的定义。Eigen常用的矩阵定义有如下:

    //2维方矩阵Eigen::Matrix2i;Eigen::Matrix2f;Eigen::Matrix2d;Eigen::Matrix2cf;Eigen::Matrix2cd;//3维方矩阵Eigen::Matrix3i;Eigen::Matrix3f;Eigen::Matrix3d;Eigen::Matrix3cf;Eigen::Matrix3cd;//4维方矩阵Eigen::Matrix4i;Eigen::Matrix4f;Eigen::Matrix4d;Eigen::Matrix4cf;Eigen::Matrix4cd; 

        Eigen库定义的都是比较常用的定义,矩阵维度小于4的,但维度超过4时,我们可以根据自己的数据进行定义,方式如下:

typedef Eigen::Matrix<float, 10, 10> Matrix10f;//10维的方正,其他类型的可以参照此定义方式进行。typedef Eigen::Matrix<double, 10, 10> Matrix10d;//10维的方正,其他类型的可以参照此定义方式进typedef Eigen::Matrix<double, 10, 10> Matrix10d;typedef Eigen::Matrix<float, 10, 15> Matrix10_15f;

2.2 、Eigen库中的向量

        正如先前所述,在Eigen库中,向量实际上是矩阵的一个特例,它们要么仅包含1行,要么仅包含1列。最常见的情形是仅含1列的向量,这种向量被称为列向量,通常简称为向量。相对地,仅含1行的向量则被称为行向量。

Eigen库中也提供了常用的向量类型的定义。Eigen定义的向量有如下:
 //2维向量Eigen::Vector2i;Eigen::Vector2f;Eigen::Vector2d;Eigen::Vector2cf;Eigen::Vector2cd;//3维向量Eigen::Vector3i;Eigen::Vector3f;Eigen::Vector3d;Eigen::Vector3cf;Eigen::Vector3cd;//4维向量Eigen::Vector4i;Eigen::Vector4f;Eigen::Vector4d;Eigen::Vector4cf;Eigen::Vector4cd;

        注意:Eigen库中上述常用定义的向量是列向量,定义方式是:

typedef Matrix<float, 3, 1> Vector3f;

        另外,行向量的定义为:

typedef Matrix<int, 1, 2> RowVector2i;

        按照自己的数据大小定义为:

typedef Eigen::Matrix<float, 10, 1> Vector10f;//10维的向量,其他类型的可以参照此定义方式进行。

2.3 、Eigen库中矩阵的动态维度(行、列)

        Eigen库的功能不仅限于处理编译时已知维度的矩阵。通过使用模板参数RowsAtCompileTimeColsAtCompileTime,我们可以指定一个特殊值Dynamic,这表明矩阵的维度在编译时是未知的,因此必须在运行时作为变量处理。在Eigen库中,这样的维度被称为动态大小;相对地,编译时已知的维度则被称为固定大小。例如,定义的 typedef MatrixXd 类型,它表示一个具有动态大小的双精度矩阵,其定义如下:

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;

        同理,可以定义了动态的向量类型VectorXi,定义如下:

typedef Matrix<int, Dynamic, 1> VectorXi;

3、Eigen库中矩阵和向量的初始化

        下面对常用矩阵和向量的初始化进行应用实例说明。

3.1、矩阵的初始化

        方式1 :‘<<’法:

Eigen:: Matrix3f m;m << 1, 2, 3,4, 5, 6,7, 8, 9;

        方式2:‘(i,j)’法:

Eigen::Matrix3f m2;m2(0, 0) = 1, m2(0, 1) = 2, m2(0, 2) = 3;m2(1, 0) = 3, m2(1, 1) = 5, m2(1, 2) = 6;m2(2, 0) = 7, m2(2, 1) = 8, m2(2, 2) = 8;

        方式3 :常数矩阵法:

   //零矩阵Eigen::Matrix4f rt1 = Eigen::Matrix4f::Zero();//单位矩阵Eigen::Matrix4f rt2 = Eigen::Matrix4f::Identity();//随机矩阵Eigen::Matrix4f rt3 = Eigen::Matrix4f::Random();

3.2、向量的初始化

        方式1: ‘<<’法:

Eigen::Vector3f v1;v1 << 1, 2, 3;

        方式2:‘(i)’法:

Eigen::Vector3f v1;v1(0) = 1;v1(1) = 2;v1(2) = 3;

        方式3: 常数矩阵法:

    //全部值是0的向量Eigen::Vector3f v2 = Eigen::Vector3f::Zero();//全部值是1的向量Eigen::Vector3f v3 = Eigen::Vector3f::Identity();//随机向量Eigen::Vector3f v4 = Eigen::Vector3f::Random();

        方式4 :构造法:

Eigen::Vector3f v5(1, 2, 3);

4、Eigen库中矩阵和向量的算术操作

        Eigen库重载了常见的C++算术运算符(例如 +、-、*),以支持矩阵和向量的算术运算,如 dot() 和 cross() 等函数。对于Matrix类(包括矩阵和向量),运算符重载仅限于支持线性代数操作。例如,Matrix1 * Matrix2 表示两个矩阵的乘积,而向量与标量的加法是不被允许的。若需执行非线性代数的各种数组运算,则必须依赖于数组运算,这部分内容将在后续讨论。

4.1 、矩阵/向量加减

示例代码:
void MatrixVector_AddAndSubtraction()
{Eigen::Matrix2d a;a << 1, 2,3, 4;Eigen::MatrixXd b(2, 2);b << 2, 3,1, 4;std::cout << "a + b =\n" << a + b << std::endl;std::cout << "a - b =\n" << a - b << std::endl;a += b;std::cout << "Now a =\n" << a << std::endl;Eigen::RowVector3d v(1, 2, 3);Eigen::RowVector3d w(1, 0, 0);std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}

        结果:

4.2、标量与矩阵/向量的乘除

        示例代码:

void MatrixVectore_ScalarMD()
{Eigen::Matrix2d a;a << 1, 1,1, 1;Eigen::Vector3d v(1, 2, 3);std::cout << "a * 3 =\n" << a * 3 << std::endl;std::cout << "3 * v =\n" << 3 * v << std::endl;v *= 2;std::cout << "Now v =\n" << v << std::endl;Eigen::Matrix2d b;b << 9, 9,9, 9;Eigen::Vector3d v2(2, 4, 6);std::cout << "a / 3 =\n" << (b / 3 )<< std::endl;std::cout << " v/2 =\n" << (v2/2) << std::endl;
}

        结果:

4.3、矩阵与矩阵、矩阵与向量的相乘

        代码示例:

void MatrixVectoreMulti()
{Eigen::Matrix2d a;a << 1, 1,1, 1;Eigen::Matrix2d b;b << 9, 9,9, 9;std::cout << "a *b =\n" << a*b << std::endl;Eigen::Vector3d v(2, 4, 6);Eigen::Matrix3d m = Eigen::Matrix3d::Random();std::cout << "m =\n" <<m << std::endl;std::cout << "v*m=\n" <<m*v << std::endl;}

        结果:

4.4、向量的点乘和叉乘

         代码示例:

void VectorDotAndCross()
{Eigen::Vector3d v(1, 2, 3);Eigen::Vector3d w(1, 1, 1);cout << "Dot product: " << v.dot(w) << endl;double dp = v.adjoint() * w; cout << "Dot product via a matrix product: " << dp << endl;cout << "Cross product:\n" << v.cross(w) << endl;
}

        结果:

4.5、Eigen库中归约操作 

        Eigen还提供了一系列归约操作,用于将给定的矩阵或向量简化为单一数值。这些操作包括计算总和(通过sum()函数)、乘积(通过prod()函数)、以及所有系数的最大值(通过maxCoeff()函数)和最小值(通过minCoeff()函数)。

        代码示例:

void ReductionOperations()
{Eigen::Matrix2d mat;mat << 4, 5,6, 7;cout << "Matrix is mat.sum():       " << mat.sum() << endl;        cout << "Matrix is mat.prod():      " << mat.prod() << endl;          cout << "Matrix is mat.mean():      " << mat.mean() << endl;       cout << "Matrix is mat.minCoeff():  " << mat.minCoeff() << endl;   cout << "Matrix is mat.maxCoeff():  " << mat.maxCoeff() << endl;   cout << "Matrix is mat.trace():     " << mat.trace() << endl;     
}

        结果:

5、矩阵的块操作

        本小节主要进行矩阵中块操作的要点说明。块是矩阵或数组的矩形部分。块表达式既可以用作右值,也可以用作左值。与通常的Eigen表达式一样,只要让编译器进行优化,块操作的运行时成本为零。Eigen中有两个版本的块操作,语法如下:

块操作

动态尺寸块

固定尺寸块

Block of size (p,q), starting at (i,j)

matrix.block(i,j,p,q);

matrix.block<p,q>(i,j);

        在Eigen库中,索引从0开始的。这两个版本均适用于处理固定尺寸和动态尺寸的矩阵与数组。从语义上讲,这两种表达方式是等效的。唯一的差异在于,当处理的块维度较小时,固定稳定版本往往能够生成更快速的代码,前提是编译时已知该尺寸。

5.1、块的基本操作 

        代码示例:

void BasicOperationBlock()
{Eigen::MatrixXf m(4, 4);m << 1, 2, 3, 4,5, 6, 7, 8,9, 10, 11, 12,13, 14, 15, 16;cout << m.block<3, 3>(1, 1) << endl << endl;for (int i = 1; i <= 3; ++i){cout << "Block of size " << i << "x" << i << endl;cout << m.block(0, 0, i, i) << endl << endl;}
}

        结果:

5.2、块左值操作

        代码示例:

void OperationBlockLetfValue()
{Eigen::Array22f m;m << 1, 2,3, 4;Eigen::Array44f a = Eigen::Array44f::Constant(0.6);cout << "Array a:" << endl << a << endl << endl;a.block<2, 2>(1, 1) = m;cout << "Here is now a with m copied into its central 2x2 block:" << endl << a << endl << endl;a.block(0, 0, 2, 3) = a.block(2, 1, 2, 3);cout << "Here is now a with bottom-right 2x3 block copied into top-left 2x3 block:" << endl << a << endl << endl;
}

        结果:

5.3、块的行和列操作

        代码示例:

void OperationBlockRowAndCol()
{Eigen::MatrixXf m(3, 3);m << 1, 2, 3,4, 5, 6,7, 8, 9;cout << "M:" << endl << m << endl;cout << "2nd Row: " << m.row(1) << endl;m.col(2) += 3 * m.col(0);cout << "After adding 3 times the first column into the third column, the matrix m is:\n";cout << m << endl;
}

        结果: 

5.4、块的角点操作 

        Eigen库提供了专门的方法来处理矩阵或数组角部或边缘的块操作。例如,.topleftcorner()方法可用于引用矩阵左上角的特定块。下表总结了不同的角点操作:

块操作

动态尺寸块

固定尺寸块

Top-left p by q block *

matrix.topLeftCorner(p,q);

matrix.topLeftCorner<p,q>();

Bottom-left p by q block *

matrix.bottomLeftCorner(p,q);

matrix.bottomLeftCorner<p,q>();

Top-right p by q block *

matrix.topRightCorner(p,q);

matrix.topRightCorner<p,q>();

Bottom-right p by q block *

matrix.bottomRightCorner(p,q);

matrix.bottomRightCorner<p,q>();

Block containing the first q rows *

matrix.topRows(q);

matrix.topRows<q>();

Block containing the last q rows *

matrix.bottomRows(q);

matrix.bottomRows<q>();

Block containing the first p columns *

matrix.leftCols(p);

matrix.leftCols<p>();

Block containing the last q columns *

matrix.rightCols(q);

matrix.rightCols<q>();

Block containing the q columns starting from i *

matrix.middleCols(i,q);

matrix.middleCols<q>(i);

Block containing the q rows starting from i *

matrix.middleRows(i,q);

matrix.middleRows<q>(i);

        示例代码: 

void CornerOperationBlock()
{Eigen::Matrix4f m=Eigen::Matrix4f::Random();cout << "m = " << endl << m << endl;cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl;cout << "m.bottomRows<2>() =" << endl << m.bottomRows<2>() << endl << endl;m.topLeftCorner(1, 3) = m.bottomRightCorner(3, 1).transpose();cout << "After assignment, m = " << endl << m << endl;
}

        结果:

6、向量的块操作 

        同样Eigen库也为向量和数组提供了块操作,格式如下表。

块操作

动态尺寸块

固定尺寸块

Block containing the first n elements *

vector.head(n);

vector.head<n>();

Block containing the last n elements *

vector.tail(n);

vector.tail<n>();

Block containing n elements, starting at position i *

vector.segment(i,n);

vector.segment<n>(i);

        代码示例: 

void VectroeOperationBlock()
{Eigen::ArrayXf a(6);a << 1, 2, 3, 4, 5, 6;cout << "a.head(3) =" << endl << a.head(3).transpose() << endl << endl;cout << "a.tail<3>() = " << endl << a.tail<3>().transpose() << endl << endl;a.segment(1, 4) *= 2;cout << "after 'a.segment(1,4) *= 2', a =" << endl << a.transpose() << endl;Eigen::VectorXf v(6);v << 11, 22, 33, 44, 55, 66;cout << "v.head(2) =" << endl << v.head(2).transpose() << endl << endl;cout << "v.tail<2>() = " << endl << v.tail<3>().transpose() << endl << endl;v.segment(1, 4) *= 2;cout << "after 'v.segment(1,4) *= 2', v =" << endl << v.transpose() << endl;}

        结果:

7、所有示例代码

        新建文件名PCLEigenmain.cpp,内容如下:

/*****************************************************************//**
* \file   PCLEigenmain.cpp
* \brief
*
* \author YZS
* \date   December 2024
*********************************************************************/
#include <iostream>              
#include <string>
#include <Eigen/Dense> //Eigen 头文件
using namespace std;void MatrixVector_AddAndSubtraction()
{Eigen::Matrix2d a;a << 1, 2,3, 4;Eigen::MatrixXd b(2, 2);b << 2, 3,1, 4;std::cout << "a + b =\n" << a + b << std::endl;std::cout << "a - b =\n" << a - b << std::endl;a += b;std::cout << "Now a =\n" << a << std::endl;Eigen::RowVector3d v(1, 2, 3);Eigen::RowVector3d w(1, 0, 0);std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}void MatrixVectore_ScalarMD()
{Eigen::Matrix2d a;a << 1, 1,1, 1;Eigen::Vector3d v(1, 2, 3);std::cout << "a * 3 =\n" << a * 3 << std::endl;std::cout << "3 * v =\n" << 3 * v << std::endl;v *= 2;std::cout << "Now v =\n" << v << std::endl;Eigen::Matrix2d b;b << 9, 9,9, 9;Eigen::Vector3d v2(2, 4, 6);std::cout << "a / 3 =\n" << (b / 3 )<< std::endl;std::cout << " v/2 =\n" << (v2/2) << std::endl;
}void MatrixVectoreMulti()
{Eigen::Matrix2d a;a << 1, 1,1, 1;Eigen::Matrix2d b;b << 9, 9,9, 9;std::cout << "a *b =\n" << a*b << std::endl;Eigen::Vector3d v(2, 4, 6);Eigen::Matrix3d m = Eigen::Matrix3d::Random();std::cout << "m =\n" <<m << std::endl;std::cout << "v*m=\n" <<m*v << std::endl;}void VectorDotAndCross()
{Eigen::Vector3d v(1, 2, 3);Eigen::Vector3d w(1, 1, 1);cout << "Dot product: " << v.dot(w) << endl;double dp = v.adjoint() * w; cout << "Dot product via a matrix product: " << dp << endl;cout << "Cross product:\n" << v.cross(w) << endl;
}void ReductionOperations()
{Eigen::Matrix2d mat;mat << 4, 5,6, 7;cout << "Matrix is mat.sum():       " << mat.sum() << endl;        cout << "Matrix is mat.prod():      " << mat.prod() << endl;          cout << "Matrix is mat.mean():      " << mat.mean() << endl;       cout << "Matrix is mat.minCoeff():  " << mat.minCoeff() << endl;   cout << "Matrix is mat.maxCoeff():  " << mat.maxCoeff() << endl;   cout << "Matrix is mat.trace():     " << mat.trace() << endl;     
}void BasicOperationBlock()
{Eigen::MatrixXf m(4, 4);m << 1, 2, 3, 4,5, 6, 7, 8,9, 10, 11, 12,13, 14, 15, 16;cout << m.block<3, 3>(1, 1) << endl << endl;for (int i = 1; i <= 3; ++i){cout << "Block of size " << i << "x" << i << endl;cout << m.block(0, 0, i, i) << endl << endl;}
}void OperationBlockLetfValue()
{Eigen::Array22f m;m << 1, 2,3, 4;Eigen::Array44f a = Eigen::Array44f::Constant(0.6);cout << "Array a:" << endl << a << endl << endl;a.block<2, 2>(1, 1) = m;cout << "Here is now a with m copied into its central 2x2 block:" << endl << a << endl << endl;a.block(0, 0, 2, 3) = a.block(2, 1, 2, 3);cout << "Here is now a with bottom-right 2x3 block copied into top-left 2x3 block:" << endl << a << endl << endl;
}void OperationBlockRowAndCol()
{Eigen::MatrixXf m(3, 3);m << 1, 2, 3,4, 5, 6,7, 8, 9;cout << "M:" << endl << m << endl;cout << "2nd Row: " << m.row(1) << endl;m.col(2) += 3 * m.col(0);cout << "After adding 3 times the first column into the third column, the matrix m is:\n";cout << m << endl;
}void CornerOperationBlock()
{Eigen::Matrix4f m=Eigen::Matrix4f::Random();cout << "m = " << endl << m << endl;cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl;cout << "m.bottomRows<2>() =" << endl << m.bottomRows<2>() << endl << endl;m.topLeftCorner(1, 3) = m.bottomRightCorner(3, 1).transpose();cout << "After assignment, m = " << endl << m << endl;
}void VectroeOperationBlock()
{Eigen::ArrayXf a(6);a << 1, 2, 3, 4, 5, 6;cout << "a.head(3) =" << endl << a.head(3).transpose() << endl << endl;cout << "a.tail<3>() = " << endl << a.tail<3>().transpose() << endl << endl;a.segment(1, 4) *= 2;cout << "after 'a.segment(1,4) *= 2', a =" << endl << a.transpose() << endl;Eigen::VectorXf v(6);v << 11, 22, 33, 44, 55, 66;cout << "v.head(2) =" << endl << v.head(2).transpose() << endl << endl;cout << "v.tail<2>() = " << endl << v.tail<3>().transpose() << endl << endl;v.segment(1, 4) *= 2;cout << "after 'v.segment(1,4) *= 2', v =" << endl << v.transpose() << endl;}int main(int argc, char* argv[])
{//MatrixVector_AddAndSubtraction();//MatrixVectore_ScalarMD();//MatrixVectoreMulti();//VectorDotAndCross();//ReductionOperations();//BasicOperationBlock();//OperationBlockLetfValue();//OperationBlockRowAndCol();//CornerOperationBlock();VectroeOperationBlock();std::cout << "Hello PCL!" << std::endl;std::system("pause");return 0;
}

至此完成第六节PCL库中Eigen数学工具库简单学习,由于Eigen库涉及的应用较多,后序还会持续更新该库的更多应用。下一节我们将进入《PCL库中点云数据的拓扑关系构建》的学习。   

相关文章:

PCL点云库入门——PCL库中Eigen数学工具库的基本使用(持续更新)

0、前言 PCL点云库中的算法都基于Eigen数学工具库来实现的&#xff0c;因此&#xff0c;掌握Eigen库对于深入理解和应用PCL点云库至关重要。Eigen库不仅提供了高效的矩阵和向量运算&#xff0c;还支持复杂的线性代数、几何变换等操作&#xff0c;为PCL点云处理提供了强大的数学…...

CLion Inlay Hints - 取消 CLion 灰色的参数和类型提示

CLion Inlay Hints - 取消 CLion 灰色的参数和类型提示 1. Parameter hints for C/C1.1. Toggle parameter hints globally 2. Type hints for C/C2.1. Toggle type hints&#xfeff; globally 3. Toggle inlay hints globallyReferences https://www.jetbrains.com/help/clio…...

2025山东科技大学考研专业课复习资料一览

[冲刺]2025年山东科技大学020200应用经济学《814经济学之西方经济学[宏观部分]》考研学霸狂刷870题[简答论述计算题]1小时前[强化]2025年山东科技大学085600材料与化工《817物理化学》考研强化检测5套卷22小时前[冲刺]2025年山东科技大学030100法学《704综合一[法理学、国际法学…...

vue3 v-model实例之二,tab标签页的实现

<template><div><Tab v-model"activeTab" :list"tabs" /><div><p>当前激活的 Tab 索引: {{ activeTab }}</p></div></div> </template><script setup> import { ref } from vue; import Tab …...

东方通TongWeb7.0.4.9M4部署SuperMap iServer 11.2.1

一、软件版本 操作系统: CentOS Linux release 7.5.1804 (Core)JDK:11.0.18东方通&#xff1a;TongWeb7.0.4.9M4SuperMap iServer&#xff1a;11.2.1 JDK和TongWeb软件分享&#xff1a; 链接: https://pan.baidu.com/s/1HGDTPnPID0PEOMbg3FjTVQ?pwdbh8v 提取码: bh8v 东方通软…...

QT绘制同心扇形

void ChartForm::paintEvent(QPaintEvent *) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);// 设置抗锯齿painter.save();// 设置无边框&#xff08;不需要设置QPen&#xff0c;因为默认是不绘制边框的&#xff09;QPen pen(Qt::NoPen);// QPen pen…...

2012年西部数学奥林匹克试题(几何)

2012/G1 △ A B C \triangle ABC △ABC 内有一点 P P P, P P P 在 A B AB AB, A C AC AC 上的投影分别为 E E E, F F F, 射线 B P BP BP, C P CP CP 分别交 △ A B C \triangle ABC △ABC 的外接圆于点 M M M, N N N. r r r 为 △ A B C \triangle ABC △ABC 的内…...

8位移位寄存器的verilog语言

module shift_register (output reg [7:0] Q, // 8位移位寄存器输出input D, // 输入数据input rst, // 复位信号input clk // 时钟信号 );always (posedge clk) beginif (!rst)Q < 8b00000000; // 复位时将Q清零elseQ < {Q[6:0], D}; // 否则…...

【苍穹外卖】学习心得体会-随笔

前言 写了很久&#xff0c;终于可以完整运行项目了&#xff0c;记录下这几天的心得体会回顾一下知识点 第一天、Git 分布式版本控制工具 一、Git概述 定义&#xff1a;是分布式版本控制工具&#xff0c;用于管理软件开发中的源代码文件&#xff0c;像Java类、xml文件、html…...

MySQL学习之表的增删改

MySQL学习之表的增删改 语法总结&#xff1a; INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...); //指定字段添加数据 INSERT INTO 表名 VALUES (值1, 值2, ...); //给全部字段添加数据 INSERT INTO 表名 VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, …...

电脑excel词典(xllex.dll)文件丢失是或损坏是什么原因?“xllex.dll文件缺失“要怎么解决?

Excel词典&#xff08;xllex.dll&#xff09;文件丢失或损坏&#xff1f;别担心&#xff0c;这里有解决之道&#xff01; 在日常的电脑使用和办公软件操作中&#xff0c;我们偶尔会碰到一些让人头疼的问题&#xff0c;比如Excel突然提示“Excel词典&#xff08;xllex.dll&…...

【CSS in Depth 2 精译_084】第 14 章:CSS 蒙版、形状与剪切概述 + 14.1:CSS 滤镜

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 14 章 蒙版、形状与剪切】 ✔️ 14.1 滤镜 ✔️ 14.1.1 滤镜的类型 ✔️14.1.2 背景滤镜 ✔️ 14.2 蒙版 文章目录 第 14 章 蒙版、形状与剪切 Masks, shapes, and…...

gorm源码解析(四):事务,预编译

文章目录 前言事务自己控制事务用 Transaction方法包装事务 预编译事务结合预编译总结 前言 前几篇文章介绍gorm的整体设计&#xff0c;增删改查的具体实现流程。本文将聚焦与事务和预编译部分 事务 自己控制事务 用gorm框架&#xff0c;可以自己控制事务的Begin&#xff0…...

前端优雅(装逼)写法(updating····)

1.>>右位移运算符取整数 它将一个数字的二进制位向右移动指定的位数&#xff0c;并在左侧填充符号位&#xff08;即负数用1填充&#xff0c;正数用0填充&#xff09;。 比如 2.99934 >> 0&#xff1a;取整结果是2&#xff0c;此处取整并非四舍五入 2.99934 会先…...

黑马Java面试教程_P7_常见集合_P4_HashMap

系列博客目录 文章目录 系列博客目录4. HashMap相关面试题4.4 面试题-HashMap的put方法的具体流程 频54.4.1 hashMap常见属性4.4.2 源码分析 HashMap的构造函数面试文稿&#xff1a; 4.5 讲一讲HashMap的扩容机制 难3频4面试文稿&#xff1a; 4.6 面试题-hashMap的寻址算法 难4…...

使用 CFD 加强水资源管理:全面概述

探索 CFD&#xff08;计算流体动力学&#xff09;在增强保护人类健康的土木和水利工程实践方面的重大贡献。 挑战 水资源管理是指规划、开发、分配和管理水资源最佳利用的做法。它包括广泛的活动&#xff0c;旨在确保水得到有效和可持续的利用&#xff0c;以满足各种需求&…...

XXE练习

pikachu-XXE靶场 1.POC:攻击测试 <?xml version"1.0"?> <!DOCTYPE foo [ <!ENTITY xxe "a">]> <foo>&xxe;</foo> 2.EXP:查看文件 <?xml version"1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SY…...

R语言读取hallmarks的gmt文档的不同姿势整理

不同格式各有所用 1.读取数据框格式的 hallmarks <- clusterProfiler::read.gmt("~/genelist/h.all.v7.4.symbols.gmt") #返回的是表格 hallmarks$term<- gsub(HALLMARK_,"",hallmarks$term)适配Y叔的clusterProfiler的后续分析,比如整理后geneli…...

【Nginx-4】Nginx负载均衡策略详解

在现代Web应用中&#xff0c;随着用户访问量的增加&#xff0c;单台服务器往往难以承受巨大的流量压力。为了解决这一问题&#xff0c;负载均衡技术应运而生。Nginx作为一款高性能的Web服务器和反向代理服务器&#xff0c;提供了多种负载均衡策略&#xff0c;能够有效地将请求分…...

Python 的 Decimal的错误计算

摘要 阐述在使用 Python的 Decimal类时&#xff0c;可能产生的错误计算。 在 详述 BigDecimal 的错误计算 中&#xff0c;笔者较为详细地说明了 Java的 BigDecimal可能出错的原因。类似地&#xff0c;Python的 decimal模块中有个 Decimal类&#xff0c;也可用于高精度的十进制…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...