您的位置:首页 > 其它

Oriented Bounding Box 碰撞检测

2016-04-03 03:32 1026 查看
rt, 这是项目中遇到的一个问题, 即: 给定两个点集, 如何判断他们是否相交。

其中, 输入自然是两个三维点集。 做法是分别求他们的包围盒, 然后看包围盒是否相交即可。

所以, 现在问题转换为给定一个三维点集, 求其包围盒。 这里有人说可以用pca求其特征向量, 这个向量就是这个点集的方向。 我觉得应该是对的, 但我没试过。

这里我采用的是网上的开元库。 省心省力。。。 网址: http://gabyx.github.io/ApproxMVBB/, 作者提供了一个库, 可以直接输出一堆点, 输出一个包围盒。

编译的步骤在官网上有, 但是有几个注意的地方:

1, 编译pugixml的时候, 不要直接从软件源里安装, 需要自己编译!, 同时, 打开长整形支持

install with #define PUGIXML_HAS_LONG_LONG enabled in pugiconfig.hpp

2, 下载的时候记得用git clone。。。 我用master的压缩包似乎有问题。

其他的没问题, 直接编译通过。 作者用了eigen的库, 里面的一些数据结构基本是eigende。

下面贴两端代码, 分别是编译好之后的测试程序, 

test。cpp

// ========================================================================================
// ApproxMVBB
// Copyright (C) 2014 by Gabriel Nützi <nuetzig (at) imes (d0t) mavt (d0t) ethz (døt) ch>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/. // ========================================================================================

#include <iostream>
#include <mex.h>

#include "ApproxMVBB/ComputeApproxMVBB.hpp"

int
main (int argc, char ** argv)
{

unsigned int nPoints = 100;

std::cout << "Sample " << nPoints
<< " points in unite cube (coordinates are in world frame I) "
<< std::endl;
ApproxMVBB::Matrix3Dyn points (3, nPoints);
points.setRandom ();

std::cout << points.col (0) << std::endl;
points.col (0) << 1, 2, 4;
std::cout << points.col (0) << std::endl;

for (int i = 0; i < 5; i++)
{
std::cout << points.col (i) << std::endl;
}

ApproxMVBB::OOBB oobb = ApproxMVBB::approximateMVBB (points, 0.001, 500, 5,
0, 5);

std::cout << "Computed OOBB: " << std::endl
<< "---> lower point in OOBB frame: "
<< oobb.m_minPoint.transpose () << std::endl
<< "---> upper point in OOBB frame: "
<< oobb.m_maxPoint.transpose () << std::endl
<< "---> coordinate transformation A_IK matrix from OOBB frame K to world frame I"
<< std::endl << oobb.m_q_KI.matrix () << std::endl
<< "---> this is also the rotation matrix R_KI which turns the world frame I into the OOBB frame K"
<< std::endl << std::endl;

// To make all points inside the OOBB :
ApproxMVBB::Matrix33 A_KI = oobb.m_q_KI.matrix ().transpose (); // faster to store the transformation matrix first
auto size = points.cols ();
for (unsigned int i = 0; i < size; ++i)
{
oobb.unite (A_KI * points.col (i));
}
std::cout << "OOBB with all point included: " << std::endl
<< "---> lower point in OOBB frame: "
<< oobb.m_minPoint.transpose () << std::endl
<< "---> upper point in OOBB frame: "
<< oobb.m_maxPoint.transpose () << std::endl;

return 0;
}


以及如何在matlab中调用。。。

// ========================================================================================
// ApproxMVBB
// Copyright (C) 2014 by Gabriel Nützi <nuetzig (at) imes (d0t) mavt (d0t) ethz (døt) ch>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/. // ========================================================================================

#include <iostream>
#include <mex.h>

#include <time.h>

#include "ApproxMVBB/ComputeApproxMVBB.hpp"

void
get_pic (double * data, int m, int n, double *minp, double *maxp,
double *matrixp)
{

ApproxMVBB::Matrix3Dyn points (3, m);

for (int i = 0; i < m; i++)
{
points.col (i) << data[i], data[i + m], data[i + m + m]
}

for (int i = 0; i < 5; i++)
{
std::cout << points.col (i) << std::endl;
}

int randseed = time(NULL);

ApproxMVBB::OOBB oobb = ApproxMVBB::approximateMVBB (points, 0.0001, 10000, 5,
0, randseed);

for (int i = 0; i < 3; i++)
{
minp[i] = oobb.m_minPoint (i);
maxp[i] = oobb.m_maxPoint (i);
}

ApproxMVBB::Matrix33 A_IK = oobb.m_q_KI.matrix ().transpose ();

for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
int ind = j * 3 + i;
matrixp[ind] = A_IK (i, j);
}

return;
}

void
mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
/* Check for proper number of arguments */
// [ min, max, matrix ] = getAABB( points )
// nx3 skeletons
if (nrhs != 1)
{
mexErrMsgIdAndTxt ("MATLAB:mexcpp:nargin",
"MEXCPP requires 1 input arguments.");
}
// min, max, matrix
else if (nlhs != 3)
{
mexErrMsgIdAndTxt ("MATLAB:mexcpp:nargout",
"MEXCPP requires 3 output argument.");
}

// skel
double *data;
int M, N;

data = mxGetPr (prhs[0]);
M = mxGetM (prhs[0]);
N = mxGetN (prhs[0]);

mexPrintf ("rows : %d\tcols : %d\n", M, N);

if (N != 3)
{
mexErrMsgIdAndTxt ("MATLAB:mexcpp:nargin",
"MEXCPP requires nx3 skeletons");
}

// output
plhs[0] = mxCreateDoubleMatrix (3, 1, mxREAL);
plhs[1] = mxCreateDoubleMatrix (3, 1, mxREAL);
plhs[2] = mxCreateDoubleMatrix (3, 3, mxREAL);
double *outData1 = (double *) mxGetPr (plhs[0]);
double *outData2 = (double *) mxGetPr (plhs[1]);
double *outData3 = (double *) mxGetPr (plhs[2]);

// run
get_pic (data, M, N, outData1, outData2, outData3);

return;
}


以及mex文件:

mex mex_boundingbox.cpp ...
-I"/home/wz/Desktop/prepare/AABB/include" ...
-I"/usr/local/include/eigen3" ...
-L"/home/wz/Desktop/prepare/AABB/lib" ...
-lApproxMVBB

a = rand(100, 3);
tic
for i = 1:10
[min, max, matrix] = mex_boundingbox(a);
end
toc

最后, matlab需要开启std=c++11的支持, 所以最好用gcc4.8级以上。

over。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: