Oriented Bounding Box 碰撞检测

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 
//
//  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 
#include 

#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 
//
//  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 
#include 

#include 

#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。



你可能感兴趣的:(matlab)