将 CGAL 与四元数结合起来合乎逻辑吗
Is it logical wanting to combine CGAL with Quaternions
我正在创建一个离散元法模拟程序,我正在使用 CGAL 来描述多面体。由于更好的数值稳定性和缺少万向节锁,我计划通过阅读文献来使用四元数来计算旋转的微分方程。但是 CGAL 似乎不支持基于四元数的旋转。 (如果我在这里不正确,请告诉我)我发现这似乎缺失有点令人惊讶,当然是因为 CGAL 喜欢绝对的准确性,这似乎很适合四元数的数值稳定性。
问题:我能否以某种方式将 Boost 四元数与 CGAL 结合使用,或者是否有任何简单的方法来实现它。如果是这样,尝试这样做是否合乎逻辑?
我认为我有的其他选择是:
- 使用 CGAL 编写我的仿射旋转微分方程并处理那里的缺点。
- 将方向存储为仿射旋转矩阵并将其转换为四元数并在差异中使用它。方程式。显然我担心这里每个时间步所需的转换步骤。
非常感谢我可能想到的任何建议或其他选项。
第一个选项:使用 Aff_transformation_3 class
CGAL 不提供四元数 class,但它确实提供了 Aff_transformation_3 class。您可以像这样轻松使用:
CGAL::Surface_mesh<Kernel> P;
std::transform( P.points_begin(), P.points_end(), P.points_begin(), yourAffineTransformation);
定义变换矩阵见this。
第二种选择:使用四元数
如果您想使用四元数,您需要使用外部库构建一个。例如你可以使用 Eigen:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> //or whichever kernel suits your needs
#include <CGAL/Surface_mesh.h>
#include <Eigen/Geometry>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Polyhedron = CGAL::Surface_mesh<Kernel>;
using Point = CGAL::Point_3<Kernel>;
// define the function that rotates your mesh
template <typename Vect, typename Quaternion>
void rotateCGALPolyhedron(Polyhedron P, Vect to_rotation_center,
Quaternion quat) {
for (auto vi : P.vertices()) {
Point p = P.point(vi);
// translate your point to the rotation center. In your case this would be
// the center of mass of the Polyhderon
Vect V(p[0] - to_rotation_center[0], p[1] - to_rotation_center[1],
p[2] - to_rotation_center[2]);
// construct the translation vector that moves your point to the rotated
// position
Vect v = quat * V; //the Vect operator*(Quaternion, Vect) must be implemented!! If you use Eigen::Quaternion you could use Eigen::Vector3d
// retranslate the point back to its initial position and translate it using
// the previously created translation vector
P.point(size_t(vi)) =
Point(to_rotation_center[0] + v[0], to_rotation_center[1] + v[1],
to_rotation_center[2] + v[2]);
}
}
int main() {
// define your rotation using eigen's quaternion class
Eigen::Quaternion<double> quad(..);
Eigen::Vector_3d centerOfMass; //find the center of mass of the mesh you want to rotate
rotateCGALPolyhedron(P.vertices.begin(), P.vertices.end(), centerOfMass,
quad);
return 0;
}
如您所见,由于 cgal 没有四元数的实现,如果您想使用四元数,则与 Aff_transformation_3 情况相比,代码很长。
我正在创建一个离散元法模拟程序,我正在使用 CGAL 来描述多面体。由于更好的数值稳定性和缺少万向节锁,我计划通过阅读文献来使用四元数来计算旋转的微分方程。但是 CGAL 似乎不支持基于四元数的旋转。 (如果我在这里不正确,请告诉我)我发现这似乎缺失有点令人惊讶,当然是因为 CGAL 喜欢绝对的准确性,这似乎很适合四元数的数值稳定性。
问题:我能否以某种方式将 Boost 四元数与 CGAL 结合使用,或者是否有任何简单的方法来实现它。如果是这样,尝试这样做是否合乎逻辑?
我认为我有的其他选择是:
- 使用 CGAL 编写我的仿射旋转微分方程并处理那里的缺点。
- 将方向存储为仿射旋转矩阵并将其转换为四元数并在差异中使用它。方程式。显然我担心这里每个时间步所需的转换步骤。
非常感谢我可能想到的任何建议或其他选项。
第一个选项:使用 Aff_transformation_3 class
CGAL 不提供四元数 class,但它确实提供了 Aff_transformation_3 class。您可以像这样轻松使用:
CGAL::Surface_mesh<Kernel> P;
std::transform( P.points_begin(), P.points_end(), P.points_begin(), yourAffineTransformation);
定义变换矩阵见this。
第二种选择:使用四元数
如果您想使用四元数,您需要使用外部库构建一个。例如你可以使用 Eigen:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> //or whichever kernel suits your needs
#include <CGAL/Surface_mesh.h>
#include <Eigen/Geometry>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Polyhedron = CGAL::Surface_mesh<Kernel>;
using Point = CGAL::Point_3<Kernel>;
// define the function that rotates your mesh
template <typename Vect, typename Quaternion>
void rotateCGALPolyhedron(Polyhedron P, Vect to_rotation_center,
Quaternion quat) {
for (auto vi : P.vertices()) {
Point p = P.point(vi);
// translate your point to the rotation center. In your case this would be
// the center of mass of the Polyhderon
Vect V(p[0] - to_rotation_center[0], p[1] - to_rotation_center[1],
p[2] - to_rotation_center[2]);
// construct the translation vector that moves your point to the rotated
// position
Vect v = quat * V; //the Vect operator*(Quaternion, Vect) must be implemented!! If you use Eigen::Quaternion you could use Eigen::Vector3d
// retranslate the point back to its initial position and translate it using
// the previously created translation vector
P.point(size_t(vi)) =
Point(to_rotation_center[0] + v[0], to_rotation_center[1] + v[1],
to_rotation_center[2] + v[2]);
}
}
int main() {
// define your rotation using eigen's quaternion class
Eigen::Quaternion<double> quad(..);
Eigen::Vector_3d centerOfMass; //find the center of mass of the mesh you want to rotate
rotateCGALPolyhedron(P.vertices.begin(), P.vertices.end(), centerOfMass,
quad);
return 0;
}
如您所见,由于 cgal 没有四元数的实现,如果您想使用四元数,则与 Aff_transformation_3 情况相比,代码很长。