【问题标题】:can't create stl containers of type AABB tree in CGAL无法在 CGAL 中创建 AABB 树类型的 stl 容器
【发布时间】:2014-03-13 16:56:36
【问题描述】:

例如,当我尝试为映射分配值时,我正在尝试创建 map<int,CGAL::AABB_tree<Traits>> 类型的 STL 映射(AABB tree's 的映射)(此代码仅用于演示目的):

//CGAL includes begin
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>
//CGAL includes end
/*
 * CGAL typedef's for initialization
 */
typedef CGAL::Simple_cartesian<double>                          K;
typedef K::FT                                                   FT;
typedef K::Point_3                                              Point_3;
typedef K::Segment_3                                            Segment;
typedef CGAL::Polyhedron_3<K>                                   Polyhedron;
typedef Polyhedron::HalfedgeDS                                  HalfedgeDS;
typedef Polyhedron::Vertex_const_iterator                       Vertex_const_iterator;
typedef Polyhedron::Facet_const_iterator                        Facet_const_iterator;
typedef Polyhedron::Halfedge_around_facet_const_circulator      Halfedge_around_facet_const_circulator;
typedef CGAL::AABB_face_graph_triangle_primitive<Polyhedron>    Primitive;
typedef CGAL::AABB_traits<K, Primitive>                         Traits;
typedef CGAL::AABB_tree<Traits>                                 Tree;
typedef Tree::Point_and_primitive_id                            Point_and_primitive_id;
//end of typedef's

BuildMesh<HalfedgeDS> mesh(V, F);
polyhedron.delegate( mesh);
myMap[someInt] = Tree(polyhedron.facets_begin(),polyhedron.facets_end(),polyhedron);

我收到以下错误:

错误 C2248: 'CGAL::AABB_tree::operator =' : 不能 访问在类 'CGAL::AABB_tree'

中声明的私有成员

我尝试查看 CGAL 的源代码,在 CGAL\AABB_tree.h 中找到以下几行:

private:
        // Disabled copy constructor & assignment operator
        typedef AABB_tree<AABBTraits> Self;
        AABB_tree(const Self& src);
        Self& operator=(const Self& src);

这意味着复制和赋值构造函数是私有的,因此无法创建 树类型的 stl 容器。

我尝试使用指针而不是我将地图更改为map&lt;int,CGAL::AABB_tree &lt; Traits &gt; * &gt; 并尝试过:

BuildMesh<HalfedgeDS> mesh(V, F);
polyhedron.delegate( mesh);
myMap[someInt] = new Tree(polyhedron.facets_begin(),polyhedron.facets_end(),polyhedron);

但是它使我的代码崩溃了。

有什么办法可以创建这种类型的 STL 容器吗?

2014 年 14 月 3 日更新

我尝试按照建议使用 Drop 的解决方案,但出现以下错误:

错误 C2248:“CGAL::AABB_tree::AABB_tree”:无法访问 在类 'CGAL::AABB_tree' 中声明的私有成员

2014 年 3 月 17 日更新

这是一个无法编译的示例代码:

#include <iostream>
#include <map>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>
using std::map;

typedef CGAL::Simple_cartesian<double> K;
typedef K::FT FT;
typedef K::Point_3 Point;
typedef K::Segment_3 Segment;
typedef CGAL::Polyhedron_3<K> Polyhedron;
typedef CGAL::AABB_face_graph_triangle_primitive<Polyhedron> Primitive;
typedef CGAL::AABB_traits<K, Primitive> Traits;
typedef CGAL::AABB_tree<Traits> Tree;
typedef Tree::Point_and_primitive_id Point_and_primitive_id;
int main()
{
    map<int,Tree> myMap;
    Point p(1.0, 0.0, 0.0);
    Point q(0.0, 1.0, 0.0);
    Point r(0.0, 0.0, 1.0);
    Point s(0.0, 0.0, 0.0);
    Polyhedron polyhedron;
    polyhedron.make_tetrahedron(p, q, r, s);

    // here i get the error
    myMap.emplace(
        std::piecewise_construct,
        std::forward_as_tuple(1),
        std::forward_as_tuple(polyhedron.facets_begin(), polyhedron.facets_end(),polyhedron));
    myMap[1].accelerate_distance_queries();
    // query point
    Point query(0.0, 0.0, 3.0);
    // computes squared distance from query
    FT sqd = myMap[1].squared_distance(query);
    std::cout << "squared distance: " << sqd << std::endl;
    // computes closest point
    Point closest = myMap[1].closest_point(query);
    std::cout << "closest point: " << closest << std::endl;
    // computes closest point and primitive id
    Point_and_primitive_id pp = myMap[1].closest_point_and_primitive(query);
    Point closest_point = pp.first;
    Polyhedron::Face_handle f = pp.second; // closest primitive id
    std::cout << "closest point: " << closest_point << std::endl;
    std::cout << "closest triangle: ( "
              << f->halfedge()->vertex()->point() << " , " 
              << f->halfedge()->next()->vertex()->point() << " , "
              << f->halfedge()->next()->next()->vertex()->point()
              << " )" << std::endl;

    return EXIT_SUCCESS;
}

有什么想法吗?

【问题讨论】:

  • 究竟是什么“崩溃”了?您使用调试器,不是吗? (智能)指针的替代方法可以是添加一个间接级别:将您的数据放入包装类并为其定义复制语义,然后制作一个包装容器。
  • 我正在编写一个 mex 文件,所以调试很困难。我确实将数据放在了一个包装类中,但是不可能编写复制语义,因为 AABB 树没有复制语义,所以我无法复制它......

标签: c++ containers computational-geometry cgal


【解决方案1】:

使用std::map::emplace() method, std::pair's piecewise constructorperfect forwarding,就地构造不可复制和不可分配的数据:

myMap.emplace(
    std::piecewise_construct,  // disambiguation hint
    std::forward_as_tuple(someInt),  // perfectly forward arguments to key_type constructor
    std::forward_as_tuple(polyhedron.facets_begin(), polyhedron.facets_end(),
        polyhedron)); // perfectly forward arguments to value_type constructor

解决方案非常冗长,但完全符合 C++11 标准。

工作示例:Coliru Viewer

编辑: 如果您的编译器不支持 std::make_tuple 而不是 std::forward_as_tuple (#include &lt;tuple&gt;),请使用 std::make_tuple

编辑2:

查看添加的代码后,我发现错误不是由map::emplace方法触发的(可以通过注释掉很容易验证),而是通过map::operator[]的后续使用。在内部,map::operator[] 使用 map::insert(检查它的源代码)。只需使用map::at() 来解决问题。示例:

FT sqd = myMap.at(1).squared_distance(query);

注意,如果找不到密钥,map::at() 会抛出异常。您可能有兴趣(取决于性能要求)通过在访问值之前检查 map::find() 来确保密钥。

还请注意,由于 CGAL 内部使用“不安全”字符串函数,您会收到详细警告。它们不是错误,可以通过添加 -D_SCL_SECURE_NO_WARNINGS 编译器标志来禁用。

希望对您有所帮助。编码愉快!

【讨论】:

  • 使用您的方法时出现以下错误:错误 C2248: 'CGAL::AABB_tree::AABB_tree' : 无法访问在类 'CGAL::AABB_tree 中声明的私有成员'
  • 检查你的代码:错误真的指向emplace()吗?检查您的编译器版本:它是否支持 C++11?我已经使用 MSVC 2013 和 GCC 4.8 进行了测试(请参阅模拟不可复制和不可分配类型的工作示例)
  • 我使用 Visual Studio 2012,因此它支持 C++ 11。只有当我尝试将 AABB 树值分配给地图时才会发生错误。我认为问题出在CGAL上。我怀疑它实际上是 CGAL 中的一个错误...当您使用 Tree 构造函数时会出现问题 Tree(...) 而不是 Tree a(...) (工作正常)。
  • @DontCareBear 我没明白。你已经指出赋值运算符和复制构造函数是私有的,所以你不能myMap[someInt] = Tree(...)。然后我向您提出了一个使用myMap.emplace() 的解决方案(没有分配或复制)。但是你仍然在某个地方分配并得到与map::emplace() 无关的错误。我哪里错了?
  • 我真的不知道怎么了。仅当我使用您建议的语法将 AABB 树添加到地图时才会发生错误: map.emplace(std::piecewise_construct,std::forward_as_tuple(idCount), std::forward_as_tuple(polyhedron.facets_begin(), polyhedron.facets_end (), 多面体));当我删除此行(并且不将 AABB 树添加到地图)时,错误消失了。这意味着即使这种不使用赋值或复制运算符的语法仍然使用来自 AABB Tree 类的私有内容。
猜你喜欢
  • 2017-12-26
  • 2020-09-23
  • 1970-01-01
  • 1970-01-01
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
  • 2014-12-30
  • 1970-01-01
相关资源
最近更新 更多