如何有效地处理 2D 和 3D 模型

计算科学 数据结构 3d
2021-12-01 04:10:52

我和我的同事开发了一个实现“3D 地质模型”类的 c++ 库。该库的目标是提供一种用于计算代码(例如有限元代码等)的数据结构

该模型类包含“实体”(即角、线、曲面、体积)。每个实体都有一个网格,它包含 3D 空间中的顶点和连接信息。

我们还想处理“二维地质模型”,它具有相同的结构(即它包含一组角、线、面)。但是这一次,这些实体拥有一个 Mesh,其中包含 2D 空间中的顶点。

一个目标是让用户能够使用相同的 API 运行他们的计算代码,即使它是在 3D 或 2D“地质模型”上。

这里有人遇到过同样的问题吗?一种解决方案是按空间维度对所有类进行模板化,但这似乎有点繁重。

干杯,

1个回答

我使用 C++ 模板在流体模拟项目中参数化尺寸。它与您的应用程序没有直接关系,但我认为一些一般的想法是相同的。

  • 向量/数组/点/顶点的向量化操作。

    我相信你已经实现了这个。

  • 提供迭代器以访问模型中的拓扑。

    通过这种方式,您可以抽象(隐藏)维度细节,例如“对于给定元素,我有多少相邻的面/边?”。

  • 首选数组结构 (SOA) 内存布局。

    在 SOA 布局中,您将来自不同对象的相同属性放在一个数组中。

    例如,这是定义顶点的常用方法:

    struct Vertex {
        VECTOR<D> position;
        double weight;
        // other attributes
    };
    std::vector<Vertex> vertices;
    

    这称为结构阵列。一个潜在的问题是布局可能因不同的尺寸而异。因此,您可能会遇到对齐问题。

    相反,我会建议 SOA 方式:

      struct Vertices {
          std::vector<VECTOR<D>> positions;
          // or
          // std::vector<double> px;
          // std::vector<double> py;
          // ...
          std::vector<double> weights;
          // other attribute arrays
      };
      Vertices vertices;
    

    当所有相同类型的属性存储在一起时,对齐问题应该会更少。

  • 在 .cpp 文件中实例化模板类。

    在 C++ 中,当编译器看不到模板类的使用时,它不会被实例化。

    如果你的 lib 和你的用户代码是分开编译的,你的 lib 将不会包含你的类实现,因为它看不到它的使用,并且编译器会在你的用户项目中抛出未定义的引用错误。

    因此,请记住在 .cpp 文件中手动为您关心的每个维度(通常是 2 和 3)实例化您的类。

一种解决方案是按空间维度对所有类进行模板化,但这似乎有点繁重。

我不确定您所说的“重”是什么意思。实际上,为每个维度实例化模板类会增加代码大小。但我在实践中没有看到这是一个问题。