我有一些点云和一些空间索引类,如QuadTree
,Octree
,Partion
尽在点云的快速查询。根据点云结构,可能适合使用给定的空间索引类型或其他类型。
所有空间索引类具有相同的公共成员:一个构造函数,insert
,lookup
和knn
。显然,实现方式不同,私有成员也不同。
class SpatialIndexType {
public:
SpatialIndexType(const std::vector<Point>&);
bool insert(const Point&);
template<typename T> void lookup(T& shape, std::vector<Point>&);
void knn(const Point&, const unsigned int, std::vector<Point>&);
}
我通常以这种方式使用我的课程(伪代码)
// Build a spatial index
SpatialIndexType index(point_cloud);
// Make successive queries of points in a shape
// (here a disc)
for(i = 0 ; i < n ; i++) {
Disc disc(x[i], y[i], radius);
std::vector<Point> pts;
index.lookup(disc, pts);
// Do something with pts which might be many lines of code
}
现在,假设我知道我的结构point_cloud
要求在运行时使用Octree而不是Quadtree 。我可以创建一个开关功能(伪代码)
do_something(point_cloud, type) {
switch(type) {
case 1: do_something_with_quadtree(point_cloud)
case 2: do_something_with_octree(point_cloud)
case 3: do_something_with_partition(point_cloud)
}
}
和我所有的do_something_with_*
功能将是严格相同的。他们将通过一个字不同:SpatialIndexType
既可为QuadTree
,Octree
,Partition
或潜在的东西。
我很确定这是避免这种愚蠢的代码重复的聪明方法。我试图从虚拟类继承,SpatialIndex
但是我陷入了lookup
无法定义的模板化成员的困境virtual
。
您可以模板化功能
template <typename SpatialIndexType>
void do_something(const std::vector<Point>& point_cloud)
{
// Build a spatial index
SpatialIndexType index(point_cloud);
// Make successive queries of points in a shape
// (here a disc)
for (int i = 0 ; i < n ; i++) {
Disc disc(x[i], y[i], radius);
std::vector<Point> pts;
index.lookup(disc, pts);
// Do something with pts which might be many lines of code
}
}
和您的运行时调度程序:
void do_something(const std::vector<Point>& point_cloud, int type) {
switch(type) {
case 1: do_something_with<Quadtree>(point_cloud);
case 2: do_something_with<Octree>(point_cloud);
case 3: do_something_with<Partition>(point_cloud);
}
}
如果必须分派几次,则可以使用std::variant
分派因素:
template <typename> struct Tag{};
using SpatialIndexTypeVariant = std::variant<Tag<QuadTree>, Tag<Octree>, Tag<PArtition>>;
SpatialIndexTypeVariant RuntimeType(int type)
{
switch (type) {
case 1: return Tag<Quadtree>();
case 2: return Tag<Octree>();
case 3: return Tag<Partition>();
}
throw std::runtime_error("Unknown type");
}
然后(C ++ 20):
std::visit([&]<typename T>(Tag<T>){ do_something_with<T>(point_cloud); }, RuntimeType(type));
对于C ++ 17,您可以将通用函数的签名更改为:
template <typename SpatialIndexType>
void do_something(Tag<SpatialIndexType>, const std::vector<Point>& point_cloud);
并使用常规的通用lambda。
std::visit([&](auto tag){ do_something_with(tag, point_cloud); }, RuntimeType(type));
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句