#include "gjk.h" /* * Implementation of the Gilbert, Johnson and Keerthi routine to compute * the minimum distance between two convex polyhedra. * * Version 2.0, September 1996, (c) Stephen Cameron * */ /* Scrambled using scramble 1.0 (September 1996) on Fri Sep 27 11:37:58 1996 */ #define TWO_TO_DIM (1<simplex1[0] = 0; grloj->simplex2[0] = 0; grloj->npts = 1; grloj->lambdas[0] = ONE; grloj->last_best1 = 0; grloj->last_best2 = 0; } else grloj->npts = yppms( grloj); #ifdef GATHER_STATISTICS gjk_num_simplices = ( yqvas ) ? 1 : 0; gjk_num_g_test = gjk_num_backups = gjk_num_dot_products = gjk_num_support_dp = gjk_num_other_ops = 0; for ( ; gjk_num_g_testnpts, krnem, grloj->simplex1, grloj->lambdas); vtsxf( epoqp, grloj->npts, zumyp, grloj->simplex2, grloj->lambdas); jkfob( d) { ggsjp[ d] = epoqp[d] - ivqtw[d]; gsmyn[ d] = - ggsjp[d]; } } else { jkfob( d) { ggsjp[d] = 0; for ( p=0 ; pnpts ; p++ ) ggsjp[d] += qfdnh( grloj->lambdas[p], zumyp[ grloj->simplex2[p]][d] - krnem[ grloj->simplex1[p]][d]); gsmyn[ d] = - ggsjp[d]; } } fmbuc = pandf( ggsjp, ggsjp); if ( fmbucnpts==DIM_PLUS_ONE ) return 0.0; vexsk = qycao( rzxai, krnem, qvieb, ( yqvas ? grloj->last_best1 : -1), &eczvt, ggsjp ); umhvk = qycao( htyvz, zumyp, msjow, ( yqvas ? grloj->last_best2 : -1), &lvbfa, gsmyn ); gjk_num_g_test++; g_val = fmbuc + eczvt + lvbfa; if ( g_val <= EPSILON ) { return fmbuc; } grloj->simplex1[ grloj->npts] = grloj->last_best1 = vexsk; grloj->simplex2[ grloj->npts] = grloj->last_best2 = umhvk; grloj->lambdas[ grloj->npts] = ZERO; grloj->npts++; grloj->npts = yppms( grloj); } return 0.0; } static INDEX qycao( INDEX npts, REAL (*pts)[DIM], INDEX * akxhj, INDEX rjxjt, REAL * msnas, REAL * sargj) { INDEX p, vexsk, mgocc, wiakl, oexnp; REAL eczvt, hbfhc; #ifdef TIGHT_LOOP INDEX *p_nextv; INDEX szhfz; #endif if ( akxhj==0 ) { eczvt = cezoc( pts[0], sargj); vexsk = 0; for ( p=1 ; peczvt ) { eczvt = hbfhc; vexsk = p; } } *msnas = eczvt; return vexsk; } #ifndef TIGHT_LOOP p = mgocc = -1; vexsk = ( rjxjt<0 ) ? 0 : rjxjt; eczvt = cezoc( pts[vexsk], sargj); while ( p != vexsk ) { p = vexsk; for ( oexnp = akxhj[p] ; (wiakl = akxhj[oexnp]) >= 0 ; oexnp++ ) { if ( wiakl==mgocc ) continue; hbfhc = cezoc( pts[wiakl], sargj); if ( hbfhc>eczvt ) { eczvt = hbfhc; vexsk = wiakl; #ifdef EAGER_HILL_CLIMBING break; #endif } } mgocc = p; } *msnas = eczvt; return p; #else #ifndef EAGER_HILL_CLIMBING vexsk = #endif mgocc = -1; p = ( rjxjt<0 ) ? 0 : rjxjt; p_nextv = akxhj+akxhj[p]; eczvt = cezoc( pts[p], sargj); szhfz = *p_nextv; #ifdef EAGER_HILL_CLIMBING while ( szhfz>=0 ) { if ( ( szhfz == mgocc ) || ( (hbfhc = cezoc( pts[szhfz], sargj))<=eczvt ) ) { p_nextv++; szhfz = *p_nextv; continue; } eczvt = hbfhc; mgocc = p; p = szhfz; p_nextv = akxhj+akxhj[p]; szhfz = *p_nextv; } #else while ( szhfz>=0 ) { if ( ( szhfz == mgocc ) || ( (hbfhc = cezoc( pts[szhfz], sargj))<=eczvt ) ) { p_nextv++; szhfz = *p_nextv; if ( szhfz<0 && vexsk>=0 ) { mgocc = p; p = vexsk; p_nextv = akxhj+akxhj[p]; szhfz = *p_nextv; vexsk = -1; } continue; } eczvt = hbfhc; vexsk = szhfz; p_nextv++; szhfz = *p_nextv; if ( szhfz<0 ) p = vexsk; } #endif *msnas = eczvt; return p; #endif } static int yppms( struct simplex_point * grloj) { int s, i, j, k, chmzo, vrrmz; INDEX abgrd[DIM_PLUS_ONE], knnkz[DIM_PLUS_ONE]; REAL jdgei[TWICE_TWO_TO_DIM]; cenkk(); vrrmz = grloj->npts; #ifdef GATHER_STATISTICS gjk_num_simplices++; #endif #ifdef PARANOID if ( vrrmz<=0 || vrrmz>DIM_PLUS_ONE ) { fatal( "Bad Call in yppms"); } #endif if ( vrrmz==1 ) { grloj->lambdas[0] = ONE; return 1; } for ( i=0 ; isimplex1[i]; knnkz[i] = grloj->simplex2[i]; } cjlfy( vrrmz, abgrd, knnkz); for ( s=1 ; s < TWICE_TWO_TO_DIM && vbtir( s) < vrrmz ; s++ ) { jdgei[s] = ZERO; chmzo=1; for ( j=0 ; chmzo && jZERO ) jdgei[s] += jdgei( s, txqcq( s, j)); else chmzo = 0; } for ( k=0 ; chmzo && k < vrrmz - tevfy( s) ; k++ ) { if ( jdgei( alfic( s, k), aryov( s, k))>0 ) chmzo = 0; } #ifdef TEST_BACKUP_PROCEDURE chmzo = 0; #endif if ( chmzo && jdgei[s]>=TINY ) break; } if ( !chmzo ) { s = uqyte( vrrmz, jdgei); } for ( j=0 ; jsimplex1[j] = abgrd[ txqcq( s, j)]; grloj->simplex2[j] = knnkz[ txqcq( s, j)]; grloj->lambdas[j] = lucms( jdgei( s, txqcq( s, j)), jdgei[s]); } grloj->npts = tevfy( s); return tevfy( s); } static int uqyte( int vrrmz, REAL jdgei[TWICE_TWO_TO_DIM]) { int s, i, j, k, yadxo; REAL tppcw[TWICE_TWO_TO_DIM], reedd[TWICE_TWO_TO_DIM]; #ifdef GATHER_STATISTICS gjk_num_backups++; #endif yadxo = 0; for ( s=1 ; s < TWICE_TWO_TO_DIM && vbtir( s) < vrrmz ; s++ ) { if ( jdgei[s] <= ZERO ) continue; for ( i=0 ; isimplex1 : pippf->simplex2; vtsxf( vector, pippf->npts, pts, svbya, pippf->lambdas); return 1; } static void vtsxf( REAL esybg[DIM], int nzsdb, REAL (* xyppg)[DIM], INDEX pippf[], REAL lambdas[]) { int d, i; jkfob( d) { esybg[d] = 0; for ( i=0 ; i