我想规范化向量,但我不明白如何做这样一个基本的操作。不存在像Vector_3::normalize()这样的直接方法
我调用squared_length(),然后调用CGAL::sqr_root()来查找向量长度。然后,当我想将向量除以它的长度时,编译器不允许,因为CGAL类型不兼容。我哪里错了?
我在这里扩展@MarcGlisse的评论。
有两种情况——你想要精确的计算,或者你不想。在第一种情况下,您可以使用Exact_predicates_exact_constructions_kernel_with_sqrt
,并且规范化向量将是精确的。
在第二种情况下,你可以使用许多核,但归一化向量的长度可能与1
略有不同。还有一些内核根本没有函数CGAL::sqrt
——但是你总是可以使用函数CGAL::to_double
将平方距离转换为double
类型。另一种方法是使用CGAL::approximate_sqrt
函数,它在必要时自动进行这种转换。这些转换使得计算不精确。请看下面的例子:
#include <iostream>
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Simple_cartesian.h>
using KernelExactWithSqrt = CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt;
using KernelExact = CGAL::Exact_predicates_exact_constructions_kernel;
using KernelInexact = CGAL::Simple_cartesian<double>;
template <typename T>
auto normalize(T const& V)
{
auto const slen = V.squared_length();
auto const d = CGAL::approximate_sqrt(slen);
return V / d;
}
template <typename T>
auto check()
{
typename T::Point_2 const p{0, 0}, q{1, 1};
auto const n = normalize(typename T::Vector_2{p, q});
return n.squared_length() == 1;
}
int main()
{
std::cout << "====== Exact kernel with square root ======" << std::endl;
std::cout << check<KernelExactWithSqrt>() << std::endl;
std::cout << "====== Inexact kernel ======" << std::endl;
std::cout << check<KernelInexact>() << std::endl;
std::cout << "====== Exact kernel with automatic conversion to double ======" << std::endl;
std::cout << check<KernelExact>() << std::endl;
}
输出:
====== Exact kernel with square root ======
1
====== Inexact kernel ======
0
====== Exact kernel with automatic conversion to double ======
0
因此,这个例子表明Exact_predicates_exact_constructions_kernel_with_sqrt
保证了规范化向量将是您所期望的。