c++ CGAL归一化向量

zzwlnbp8  于 2023-01-03  发布在  其他
关注(0)|答案(1)|浏览(294)

我想对向量进行归一化,但是我不知道如何进行这样一个基本操作。不存在像Vector_3::normalize()这样的直接方法。
我调用squared_length()然后调用CGAL::sqr_root()来求向量的长度,然后当我想把向量除以它的长度时,编译器不允许,因为CGAL类型不兼容,我哪里错了?

vyswwuz2

vyswwuz21#

我在这里扩展了@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保证了归一化向量将是您所期望的。

相关问题