【问题标题】:Generic KDTree in C++C++ 中的通用 KDTree
【发布时间】:2021-12-04 20:22:52
【问题描述】:

我想在 C++ 中有一个通用的 KDTree 实现,它可以容纳任何类型的 positionable 对象。此类对象具有 2D 位置。

不幸的是。可定位类可能有不同的获取位置的方式。

  • 吸气剂getX() 和getY()
  • std::pair
  • sf::Vector2f
  • ...

将这些类包装到我的 KDTree 中的正确方法是什么?

我的树由以下节点组成:

template <typename T>
struct Node {
    int id;
    T element;
    Node *left, *right;
    Node(T element) : element(element), left(NULL), right(NULL)
    {
        static int id = 0;
        this->id = id++;
    }
};

不知何故,我希望有一个通用的 getter 到 T element 的位置。

一种可能的解决方案是定义一个可定位的接口:

struct KDTreeElement {
    virtual getX() = 0;
    virtual getY() = 0;
}

这种方法的缺点是可定位元素必须知道KDTree库

有什么选择?

【问题讨论】:

    标签: c++ oop


    【解决方案1】:

    查看boost geometry 的设计原理以找到解决此问题的方法。该方法归结为以下步骤:

    1. 声明一个从类型中提取位置信息的类模板,例如

      template <class Geometry>
      struct Position;
      
    2. 要使您的 kd 树可用于新类型,例如 MyAwesome2dPoint,请专门为此模板。在特化中,您可以使用类型的获取位置的方法:

      template <>
      struct Position<MyAwesome2dPoint>
      {
          static float getX(MyAwesome2dPoint const& p) { return p.x; }
          static float getY(MyAwesome2dPoint const& p) { return p.y; } 
      }
      
    3. 在你的 kd 树中使用这种类型系统,即不是直接访问位置,而是通过 Position 类:

      class KdTree 
      {
          template <class PointType>
          auto contains(PointType const& g)
          {
              // Geometric properties are accessed through the traits system.
              return contains_impl(
                  Position<PointType>::getX(g), 
                  Position<PointType>::getY(g));
          }
      }
      
    4. 为了额外的功劳,创建一个概念以避免在使用尚未配置为与您的库一起使用的类型时出现奇怪的编译错误:

      template <class G>
      concept Positionable = requires (G g) { 
          Position<G>::getX() + Position<G>::getY(); 
      }; 
      
      // So now you can explicitly operate on such types
      template <Positionable G>
      auto contains(G const& g)
      {
      }
      

    没有继承,没有虚拟,没有对现有类型的修改。只需创建一个可以为每个人(甚至是 C 类型)专门化的层,你就可以开始了。进一步抽象时,概念将挽救您的生命,例如boost 几何可以推广到N 维度、不同的坐标系等等。

    【讨论】:

    • 哇!这正是我一直在寻找的答案:)
    猜你喜欢
    • 2010-09-20
    • 2011-06-05
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2016-07-20
    • 2012-05-19
    相关资源
    最近更新 更多