2026-07-23 05:27:51 +00:00
|
|
|
|
#pragma once
|
2026-07-27 22:29:06 +08:00
|
|
|
|
#include "vde/core/plane.h"
|
2026-07-23 05:27:51 +00:00
|
|
|
|
#include "vde/core/point.h"
|
|
|
|
|
|
#include <Eigen/Geometry>
|
|
|
|
|
|
|
|
|
|
|
|
namespace vde::core {
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 三维仿射变换类型
|
|
|
|
|
|
*
|
|
|
|
|
|
* 基于 Eigen::Transform,支持平移、旋转、缩放和它们的组合。
|
|
|
|
|
|
* 使用 4×4 齐次矩阵表示。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
using Transform3D = Eigen::Transform<double, 3, Eigen::Affine>;
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 创建平移变换
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param v 平移向量
|
|
|
|
|
|
* @return 平移变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
|
* auto T = translate(Vector3D(1, 2, 3));
|
|
|
|
|
|
* Point3D p2 = T * Point3D(0,0,0); // p2 == (1,2,3)
|
|
|
|
|
|
* @endcode
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
inline Transform3D translate(const Vector3D& v) {
|
|
|
|
|
|
return Transform3D(Eigen::Translation<double, 3>(v));
|
|
|
|
|
|
}
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 创建平移变换(分量形式)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param x X 方向位移
|
|
|
|
|
|
* @param y Y 方向位移
|
|
|
|
|
|
* @param z Z 方向位移
|
|
|
|
|
|
* @return 平移变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
inline Transform3D translate(double x, double y, double z) {
|
|
|
|
|
|
return translate(Vector3D(x, y, z));
|
|
|
|
|
|
}
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 创建旋转变换(轴-角表示)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param axis 旋转轴(自动归一化)
|
|
|
|
|
|
* @param angle_rad 旋转角度(弧度)
|
|
|
|
|
|
* @return 旋转变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
|
* // 绕 Z 轴旋转 90°
|
|
|
|
|
|
* auto R = rotate(Vector3D::UnitZ(), M_PI / 2);
|
|
|
|
|
|
* @endcode
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
inline Transform3D rotate(const Vector3D& axis, double angle_rad) {
|
|
|
|
|
|
return Transform3D(Eigen::AngleAxis<double>(angle_rad, axis.normalized()));
|
|
|
|
|
|
}
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 绕 X 轴旋转
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param rad 旋转角度(弧度)
|
|
|
|
|
|
* @return 旋转变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
inline Transform3D rotate_x(double rad) { return rotate(Vector3D::UnitX(), rad); }
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 绕 Y 轴旋转
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param rad 旋转角度(弧度)
|
|
|
|
|
|
* @return 旋转变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
inline Transform3D rotate_y(double rad) { return rotate(Vector3D::UnitY(), rad); }
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 绕 Z 轴旋转
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param rad 旋转角度(弧度)
|
|
|
|
|
|
* @return 旋转变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
inline Transform3D rotate_z(double rad) { return rotate(Vector3D::UnitZ(), rad); }
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 创建非均匀缩放变换
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param sx X 方向缩放因子
|
|
|
|
|
|
* @param sy Y 方向缩放因子
|
|
|
|
|
|
* @param sz Z 方向缩放因子
|
|
|
|
|
|
* @return 缩放变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @note 非均匀缩放可能导致法线方向不准确;使用场景中应考虑法线变换 = (M^{-1})^T
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
inline Transform3D scale(double sx, double sy, double sz) {
|
|
|
|
|
|
return Transform3D(Eigen::Scaling(sx, sy, sz));
|
|
|
|
|
|
}
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 创建均匀缩放变换
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param s 各方向统一的缩放因子
|
|
|
|
|
|
* @return 缩放变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
inline Transform3D scale(double s) { return scale(s, s, s); }
|
|
|
|
|
|
|
2026-07-27 22:29:06 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 创建关于过原点平面的镜面反射变换
|
|
|
|
|
|
*
|
|
|
|
|
|
* 反射矩阵为 \f$ M = I - 2 \cdot \hat{n} \hat{n}^T \f$,
|
|
|
|
|
|
* 其中 \f$ \hat{n} \f$ 是单位法向量。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param normal 平面法向量(自动归一化)
|
|
|
|
|
|
* @return 镜面反射变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
|
* // 关于 YZ 平面(法向量 X 轴)反射
|
|
|
|
|
|
* auto R = mirror(Vector3D::UnitX());
|
|
|
|
|
|
* Point3D p2 = R * Point3D(3, 1, 0); // p2 == (-3, 1, 0)
|
|
|
|
|
|
* @endcode
|
|
|
|
|
|
*
|
|
|
|
|
|
* @note 反射平面过原点,不能处理一般位置平面。使用 mirror_about_plane() 处理任意平面。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @see mirror_about_plane
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline Transform3D mirror(const Vector3D& normal) {
|
|
|
|
|
|
Vector3D n = normal.normalized();
|
|
|
|
|
|
Eigen::Matrix3d refl = Eigen::Matrix3d::Identity() - 2.0 * n * n.transpose();
|
|
|
|
|
|
Transform3D T;
|
|
|
|
|
|
T.linear() = refl;
|
|
|
|
|
|
T.translation().setZero();
|
|
|
|
|
|
return T;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 创建关于任意平面的镜面反射变换
|
|
|
|
|
|
*
|
|
|
|
|
|
* 一般位置平面方程为 \f$ \hat{n} \cdot x + d = 0 \f$,
|
|
|
|
|
|
* 反射变换为:
|
|
|
|
|
|
* \f[
|
|
|
|
|
|
* T = \begin{bmatrix} I - 2\hat{n}\hat{n}^T & -2d\hat{n} \\ 0 & 1 \end{bmatrix}
|
|
|
|
|
|
* \f]
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param plane 反射平面(法向量自动归一化)
|
|
|
|
|
|
* @return 镜面反射变换矩阵
|
|
|
|
|
|
*
|
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
|
* Plane3D plane(Point3D(1, 0, 0), Vector3D::UnitX());
|
|
|
|
|
|
* auto R = mirror_about_plane(plane);
|
|
|
|
|
|
* // 点 (3, 0, 0) 到平面距离为 2,反射后变为 (-1, 0, 0)
|
|
|
|
|
|
* Point3D p2 = R * Point3D(3, 0, 0);
|
|
|
|
|
|
* @endcode
|
|
|
|
|
|
*
|
|
|
|
|
|
* @note 平面法向量在构造 Plane3D 时已归一化,无需额外处理。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @see mirror
|
|
|
|
|
|
* @ingroup core
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline Transform3D mirror_about_plane(const Plane3D& plane) {
|
|
|
|
|
|
const Vector3D& n = plane.normal();
|
|
|
|
|
|
double d = plane.d();
|
|
|
|
|
|
Eigen::Matrix3d refl = Eigen::Matrix3d::Identity() - 2.0 * n * n.transpose();
|
|
|
|
|
|
Transform3D T;
|
|
|
|
|
|
T.linear() = refl;
|
|
|
|
|
|
T.translation() = -2.0 * d * n;
|
|
|
|
|
|
return T;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-23 05:27:51 +00:00
|
|
|
|
} // namespace vde::core
|