使用C ++中的单元列表/切片/网格进行冲突检测的最佳数据结构

时间:2016-06-19 22:16:57

标签: c++ algorithm

我是c +的新手并且基于这个问题:Collision detection of huge number of circles我想实现单元格列表,这里也有描述:https://en.wikipedia.org/wiki/Cell_lists以便从碰撞检测算法中获得更好的性能。 围绕这个主题可能有很多不同的算法,但我想关注这个。

现在我正在计算2D区域上具有相同尺寸的n个球体之间的碰撞。 我将区域划分为形成网格的单元格。 网格是用于单元格位置的2D数组,3是用于存储当前在该网格单元格中的球体数量的向量。

std::array<std::array<std::vector<int>, cols>, rows> grid;

我可以通过计算得到每个球在网格中的位置:

row = x/cell_width;
col = y/cell_height;

然后我可以将球号添加到相应的单元格中:

grid[row][col].push_back(ball);

然后我检查每个网格单元格中是否有球。如果是的话,我加入来自实际和周围单元格的所有球,形成一个向量(网格球),并对该组中的碰撞进行粗暴检查。

for( int i = 1; i <rows; i = i + 1 ){
        for( int j = 1; j <cols; j = j + 1 ){
            if (grid[i][j].size()!=0){ 
                gridballs=grid[i][j];
                int nextx[]={1,1,0,-1,-1,-1,0,1}; 
                int nexty[]={0,1,1,1,0,-1,-1,-1};
                for( int k = 1; k <8; k = k + 1 ){
                    if (grid[i+nextx[k]][j+nexty[k]].size()!=0){   
                        gridballs.insert(gridballs.end(), grid[i+nextx[k]][j+nexty[k]].begin(), grid[i+nextx[k]][j+nexty[k]].end());
                    }
                }
         collisioncheck (gridballs);
        }
    }
}

}

执行此操作时出现了以下问题:

比在2D阵列中使用矢量更好的结构是什么?网格中的所有内容总是会发生变化,我认为不断添加和重置向量需要花费大量时间?

通过每次都包括周围的细胞,多次检查很多细胞,我不会失去很多表现吗?有没有办法绕过这个或者我错过了什么?

确保我不会两次测试一对球体的有效方法是什么?

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

首先,你的循环写得非常糟糕。而不是:

            gridballs=grid[i][j];
            int nextx[]={1,1,0,-1,-1,-1,0,1}; 
            int nexty[]={0,1,1,1,0,-1,-1,-1};
            for( int k = 1; k <8; k = k + 1 ){
                if (grid[i+nextx[k]][j+nexty[k]].size()!=0){   
                    gridballs.insert(gridballs.end(), grid[i+nextx[k]][j+nexty[k]].begin(), grid[i+nextx[k]][j+nexty[k]].end());
                }
            }

尝试:

balls.clear();
for (int dx=-1; dx<=1; dx++)
    for (int dy=-1; dy<=1; dy++) {
        const std::vector<int>& cell = grid[i+dx][j+dy];
        balls.insert(balls.end(), cell.begin(), cell.end());
    }

其次,使用++i++j(或i++j++)代替i = i + 1j = j + 1

关于你的问题,碰撞检测的良好结构是四叉树(在2d中)或八叉树(在3d中)。类似的东西:

class Quadtree {
public:
    Quadtree(const vector<int>& vBalls, Quadtree* parent=NULL);
    int size() const {return nBalls;}
    bool empty() const {return nBalls == 0;}
    bool IsInside(double x, double y, double r) const; // is the ball completely inside the square?
    bool IsOutside(double x, double y, double r) const; // is the ball completely outside the square?
    // ... other member functions
private:
    double xMin, yMin, xMax, yMax; // all balls must be within this square
    vector<int> vBigBalls; // balls which occupy more than one sub-square
    vector<Quadtree> vSubsquares; // 4 subsquares
    int nBalls; // total number of balls in the square and subsquares
    Quadtree* parent; // not sure if you need this
}