如何将 write_ply_with_properties() 与 Point_set_3 一起使用

How to use write_ply_with_properties() with Point_set_3

我有一个 CGAL::Point_set_3 点集,其中包含点法线和颜色。我想使用 write_ply_with_properties() 函数将所有属性保存到 PLY 文件。 我的目标是使完整版工作(见下面的代码),但即使是简单版本也无法编译,与完整版出现相同的错误。

我使用 CGAL 4.14 版和 gcc 7.4.0 开发 Linux。

代码如下:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Point_set_3/IO.h>

#include <tuple> // for std::tie
#include <fstream>


typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;


int main(int argc, char*argv[])
{
  Point_set points;
  points.insert(Point(1., 2., 3.));
  points.insert(Point(4., 5., 6.));

  // add normal map
  points.add_normal_map();
  auto normal_map = points.normal_map();

  // add color map
  typedef Point_set::Property_map< Vector > ColorMap;
  bool success = false;
  ColorMap color_map;
  std::tie(color_map, success) =
      points.add_property_map< Vector >("color");
  assert(success);

  // populate normal and color map
  for(auto it = points.begin(); it != points.end(); ++it)
  {
    normal_map[*it] = Vector(10., 11., 12.);
    color_map[*it] = Vector(20., 21., 22.);
  }

  std::ofstream out("out.ply");
#if 1
  // simple version
  if(!out || !CGAL::write_ply_points_with_properties(
                  out,
                  points.points(), // const PointRange
                  CGAL::make_ply_point_writer(points.point_map())))
#else
  // full version
  if(!out || !CGAL::write_ply_points_with_properties(
                  out,
                  points.points(), // const PointRange
                  CGAL::make_ply_point_writer(points.point_map()),
                  CGAL::make_ply_normal_writer(points.normal_map()),
                  std::make_tuple(color_map,
                                  CGAL::PLY_property< double >("red"),
                                  CGAL::PLY_property< double >("green"),
                                  CGAL::PLY_property< double >("blue"))))
#endif
  {
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

编译错误为:

...
/usr/include/boost/property_map/property_map.hpp:303:54: error: no match for ‘operator[]’ (operand types are ‘const CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Property_map<CGAL::Point_3<CGAL::Epick> >’ and ‘const CGAL::Point_3<CGAL::Epick>’)
     Reference v = static_cast<const PropertyMap&>(pa)[k];
CGAL-4.14/include/CGAL/Surface_mesh/Properties.h:567:15: note: candidate: CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::reference CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::operator[](const I&) [with I = CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Index; T = CGAL::Point_3<CGAL::Epick>; CRTP_derived_class = CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Property_map<CGAL::Point_3<CGAL::Epick> >; CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::reference = CGAL::Point_3<CGAL::Epick>&]
     reference operator[](const I& i)
               ^~~~~~~~
CGAL-4.14/include/CGAL/Surface_mesh/Properties.h:567:15: note:   no known conversion for argument 1 from ‘const CGAL::Point_3<CGAL::Epick>’ to ‘const CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Index&’

我该如何解决?

您的代码中的问题是您正在使用 CGAL::Point_set_3 的方法 points(),其中 returns 类型为 CGAL::Point_set_3::Point_range 的点范围,而 属性 您使用的映射(points.point_map() 等)直接应用于类型 CGAL::Point_set_3

所以你应该简单地在 points 上调用 write_ply_points_with_properties(),而不是在 points.points() 上调用 write_ply_points_with_properties()

另请注意,如果您将颜色存储在简单类型上(例如,使用三个 Point_set_3 类型的 unsigned char 属性),您可以利用函数 CGAL::write_ply_point_set()自动写入它找到的所有 simply-typed 属性,这使得使用起来非常简单(只需执行 CGAL::write_ply_point_set(out, points) 即可)。

最后一件事实际上是与您的问题无关的细节,但您应该避免使用 CGAL::Vector_3 来存储除实际几何 3D 矢量(如您的情况下的颜色)之外的任何其他内容。这会使您的代码更难阅读,并且如果将颜色编码为 0 到 255 之间的整数值(这就是 unsigned char 的用途),这也是一种非常低效的存储颜色的方法。