bestfitobb.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <assert.h>
6 
63 // compute the 'best fit' oriented bounding box of an input point cloud by doing an exhaustive search.
64 // it spins the point cloud around searching for the minimal volume. It keeps narrowing down until
65 // it fails to find a better fit. The only dependency is on 'double_math'
66 //
67 // The inputs are:
68 //
69 // vcount : number of input vertices in the point cloud.
70 // points : a pointer to the first vertex.
71 // pstride : The stride between each point measured in bytes.
72 //
73 // The outputs are:
74 //
75 // sides : The length of the sides of the OBB as X, Y, Z distance.
76 // matrix : A pointer to a 4x4 matrix. This will contain the 3x3 rotation and the translation component.
77 // pos : The center of the OBB
78 // quat : The orientation of the OBB expressed as quaternion in the form of X,Y,Z,W
79 //
80 //
81 // Please email bug fixes or improvements to John W. Ratcliff at mailto:jratcliff@infiniplex.net
82 //
83 // If you find this source code useful donate a couple of bucks to my kid's fund raising website at
84 // www.amillionpixels.us
85 //
86 // More snippets at: www.codesuppository.com
87 //
88 
89 
90 #include "bestfitobb.h"
91 #include "float_math.h"
92 
93 namespace ConvexDecomposition
94 {
95 
96 // computes the OBB for this set of points relative to this transform matrix.
97 void computeOBB(unsigned int vcount,const double *points,unsigned int pstride,double *sides,double *matrix)
98 {
99  const char *src = (const char *) points;
100 
101  double bmin[3] = { 1e9, 1e9, 1e9 };
102  double bmax[3] = { -1e9, -1e9, -1e9 };
103 
104  for (unsigned int i=0; i<vcount; i++)
105  {
106  const double *p = (const double *) src;
107  double t[3];
108 
109  fm_inverseRT(matrix, p, t ); // inverse rotate translate
110 
111  if ( t[0] < bmin[0] ) bmin[0] = t[0];
112  if ( t[1] < bmin[1] ) bmin[1] = t[1];
113  if ( t[2] < bmin[2] ) bmin[2] = t[2];
114 
115  if ( t[0] > bmax[0] ) bmax[0] = t[0];
116  if ( t[1] > bmax[1] ) bmax[1] = t[1];
117  if ( t[2] > bmax[2] ) bmax[2] = t[2];
118 
119  src+=pstride;
120  }
121 
122  double center[3];
123 
124  sides[0] = bmax[0]-bmin[0];
125  sides[1] = bmax[1]-bmin[1];
126  sides[2] = bmax[2]-bmin[2];
127 
128  center[0] = sides[0]*0.5f+bmin[0];
129  center[1] = sides[1]*0.5f+bmin[1];
130  center[2] = sides[2]*0.5f+bmin[2];
131 
132  double ocenter[3];
133 
134  fm_rotate(matrix,center,ocenter);
135 
136  matrix[12]+=ocenter[0];
137  matrix[13]+=ocenter[1];
138  matrix[14]+=ocenter[2];
139 
140 }
141 
142 void computeBestFitOBB(unsigned int vcount,const double *points,unsigned int pstride,double *sides,double *matrix)
143 {
144 
145  double bmin[3];
146  double bmax[3];
147 
148  fm_getAABB(vcount,points,pstride,bmin,bmax);
149 
150  double center[3];
151 
152  center[0] = (bmax[0]-bmin[0])*0.5f + bmin[0];
153  center[1] = (bmax[1]-bmin[1])*0.5f + bmin[1];
154  center[2] = (bmax[2]-bmin[2])*0.5f + bmin[2];
155 
156  double ax = 0;
157  double ay = 0;
158  double az = 0;
159 
160  double sweep = 45.0f; // 180 degree sweep on all three axes.
161  double steps = 7.0f; // 7 steps on each axis)
162 
163  double bestVolume = 1e9;
164  double angle[3];
165 
166  while ( sweep >= 1 )
167  {
168 
169  bool found = false;
170 
171  double stepsize = sweep / steps;
172 
173  for (double x=ax-sweep; x<=ax+sweep; x+=stepsize)
174  {
175  for (double y=ay-sweep; y<=ay+sweep; y+=stepsize)
176  {
177  for (double z=az-sweep; z<=az+sweep; z+=stepsize)
178  {
179  double pmatrix[16];
180 
182 
183  pmatrix[3*4+0] = center[0];
184  pmatrix[3*4+1] = center[1];
185  pmatrix[3*4+2] = center[2];
186 
187  double psides[3];
188 
189  computeOBB( vcount, points, pstride, psides, pmatrix );
190 
191  double volume = psides[0]*psides[1]*psides[2]; // the volume of the cube
192 
193  if ( volume < bestVolume )
194  {
195  bestVolume = volume;
196 
197  sides[0] = psides[0];
198  sides[1] = psides[1];
199  sides[2] = psides[2];
200 
201  angle[0] = ax;
202  angle[1] = ay;
203  angle[2] = az;
204 
205  memcpy(matrix,pmatrix,sizeof(double)*16);
206  found = true; // yes, we found an improvement.
207  }
208  }
209  }
210  }
211 
212  if ( found )
213  {
214 
215  ax = angle[0];
216  ay = angle[1];
217  az = angle[2];
218 
219  sweep*=0.5f; // sweep 1/2 the distance as the last time.
220  }
221  else
222  {
223  break; // no improvement, so just
224  }
225 
226  }
227 
228 }
229 
230 
231 void computeBestFitOBB(unsigned int vcount,const double *points,unsigned int pstride,double *sides,double *pos,double *quat)
232 {
233  double matrix[16];
234 
235  computeBestFitOBB(vcount,points,pstride,sides,matrix);
236  fm_getTranslation(matrix,pos);
237  fm_matrixToQuat(matrix,quat);
238 
239 }
240 
241 
242 void computeBestFitABB(unsigned int vcount,const double *points,unsigned int pstride,double *sides,double *pos)
243 {
244  double bmin[3];
245  double bmax[3];
246 
247  bmin[0] = points[0];
248  bmin[1] = points[1];
249  bmin[2] = points[2];
250 
251  bmax[0] = points[0];
252  bmax[1] = points[1];
253  bmax[2] = points[2];
254 
255  const char *cp = (const char *) points;
256  for (unsigned int i=0; i<vcount; i++)
257  {
258  const double *p = (const double *) cp;
259 
260  if ( p[0] < bmin[0] ) bmin[0] = p[0];
261  if ( p[1] < bmin[1] ) bmin[1] = p[1];
262  if ( p[2] < bmin[2] ) bmin[2] = p[2];
263 
264  if ( p[0] > bmax[0] ) bmax[0] = p[0];
265  if ( p[1] > bmax[1] ) bmax[1] = p[1];
266  if ( p[2] > bmax[2] ) bmax[2] = p[2];
267 
268  cp+=pstride;
269  }
270 
271 
272  sides[0] = bmax[0] - bmin[0];
273  sides[1] = bmax[1] - bmin[1];
274  sides[2] = bmax[2] - bmin[2];
275 
276  pos[0] = bmin[0]+sides[0]*0.5f;
277  pos[1] = bmin[1]+sides[1]*0.5f;
278  pos[2] = bmin[2]+sides[2]*0.5f;
279 
280 }
281 
282 
283 void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *pos,float *quat) // the float version of the routine.
284 {
285  double *temp = new double[vcount*3];
286  const char *src = (const char *)points;
287  double *dest = temp;
288  for (unsigned int i=0; i<vcount; i++)
289  {
290  const float *s = (const float *) src;
291  temp[0] = s[0];
292  temp[1] = s[1];
293  temp[2] = s[2];
294  temp+=3;
295  s+=pstride;
296  }
297 
298  double dsides[3];
299  double dpos[3];
300  double dquat[3];
301 
302  computeBestFitOBB(vcount,temp,sizeof(double)*3,dsides,dpos,dquat);
303 
304  if ( sides )
305  {
306  sides[0] = (float) dsides[0];
307  sides[1] = (float) dsides[1];
308  sides[2] = (float) dsides[2];
309  }
310  if ( pos )
311  {
312  pos[0] = (float) dpos[0];
313  pos[1] = (float) dpos[1];
314  pos[2] = (float) dpos[2];
315  }
316  if ( quat )
317  {
318  quat[0] = (float) dquat[0];
319  quat[1] = (float) dquat[1];
320  quat[2] = (float) dquat[2];
321  quat[3] = (float) dquat[3];
322  }
323 
324  delete temp;
325 
326 }
327 
328 void computeBestFitABB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *pos)
329 {
330  float bmin[3];
331  float bmax[3];
332 
333  bmin[0] = points[0];
334  bmin[1] = points[1];
335  bmin[2] = points[2];
336 
337  bmax[0] = points[0];
338  bmax[1] = points[1];
339  bmax[2] = points[2];
340 
341  const char *cp = (const char *) points;
342  for (unsigned int i=0; i<vcount; i++)
343  {
344  const float *p = (const float *) cp;
345 
346  if ( p[0] < bmin[0] ) bmin[0] = p[0];
347  if ( p[1] < bmin[1] ) bmin[1] = p[1];
348  if ( p[2] < bmin[2] ) bmin[2] = p[2];
349 
350  if ( p[0] > bmax[0] ) bmax[0] = p[0];
351  if ( p[1] > bmax[1] ) bmax[1] = p[1];
352  if ( p[2] > bmax[2] ) bmax[2] = p[2];
353 
354  cp+=pstride;
355  }
356 
357 
358  sides[0] = bmax[0] - bmin[0];
359  sides[1] = bmax[1] - bmin[1];
360  sides[2] = bmax[2] - bmin[2];
361 
362  pos[0] = bmin[0]+sides[0]*0.5f;
363  pos[1] = bmin[1]+sides[1]*0.5f;
364  pos[2] = bmin[2]+sides[2]*0.5f;
365 
366 }
367 
368 };
ConvexDecomposition::fm_matrixToQuat
void fm_matrixToQuat(const double *matrix, double *quat)
Definition: float_math.cpp:251
ConvexDecomposition::fm_getTranslation
void fm_getTranslation(const double *matrix, double *t)
Definition: float_math.cpp:244
ConvexDecomposition::fm_rotate
void fm_rotate(const double *matrix, const double *v, double *t)
Definition: float_math.cpp:331
ConvexDecomposition::computeBestFitOBB
void computeBestFitOBB(unsigned int vcount, const double *points, unsigned int pstride, double *sides, double *matrix)
Definition: bestfitobb.cpp:142
float_math.h
ConvexDecomposition
Definition: bestfit.cpp:75
ConvexDecomposition::fm_inverseRT
void fm_inverseRT(const double *matrix, const double *pos, double *t)
Definition: float_math.cpp:86
ConvexDecomposition::fm_getAABB
void fm_getAABB(unsigned int vcount, const double *points, unsigned int pstride, double *bmin, double *bmax)
Definition: float_math.cpp:134
ConvexDecomposition::computeBestFitABB
void computeBestFitABB(unsigned int vcount, const double *points, unsigned int pstride, double *sides, double *pos)
Definition: bestfitobb.cpp:242
ConvexDecomposition::computeOBB
void computeOBB(unsigned int vcount, const double *points, unsigned int pstride, double *sides, double *matrix)
Definition: bestfitobb.cpp:97
ConvexDecomposition::fm_eulerMatrix
void fm_eulerMatrix(double ax, double ay, double az, double *matrix)
Definition: float_math.cpp:127
bestfitobb.h
ConvexDecomposition::FM_DEG_TO_RAD
const double FM_DEG_TO_RAD
Definition: float_math.h:83


convex_decomposition
Author(s): John W. Ratcliff
autogenerated on Wed Mar 2 2022 00:04:59