MinCircle2<Real>::MinCircle2 (int numPoints, const Vector2<Real>* points, Circle2<Real>& minimal, Real epsilon) : mEpsilon(epsilon) { mUpdate[0] = 0; mUpdate[1] = &MinCircle2<Real>::UpdateSupport1; mUpdate[2] = &MinCircle2<Real>::UpdateSupport2; mUpdate[3] = &MinCircle2<Real>::UpdateSupport3; Support support; Real distDiff; if (numPoints >= 1) { // Create identity permutation (0,1,...,numPoints-1). Vector2<Real>** permuted = new1<Vector2<Real>*>(numPoints); int i; for (i = 0; i < numPoints; ++i) { permuted[i] = (Vector2<Real>*)&points[i]; } // Generate random permutation. for (i = numPoints - 1; i > 0; --i) { int j = rand() % (i+1); if (j != i) { Vector2<Real>* save = permuted[i]; permuted[i] = permuted[j]; permuted[j] = save; } } minimal = ExactCircle1(*permuted[0]); support.Quantity = 1; support.Index[0] = 0; // The previous version of the processing loop is // i = 1; // while (i < numPoints) // { // if (!support.Contains(i, permuted, mEpsilon)) // { // if (!Contains(*permuted[i], minimal, distDiff)) // { // UpdateFunction update = mUpdate[support.Quantity]; // Circle2<Real> circle = (this->*update)(i, permuted, // support); // if (circle.Radius > minimal.Radius) // { // minimal = circle; // i = 0; // continue; // } // } // } // ++i; // } // This loop restarts from the beginning of the point list each time // the circle needs updating. Linus Källberg (Computer Science at // Mälardalen University in Sweden) discovered that performance is // better when the remaining points in the array are processed before // restarting. The points processed before the point that caused the // update are likely to be enclosed by the new circle (or near the // circle boundary) because they were enclosed by the previous circle. // The chances are better that points after the current one will cause // growth of the bounding circle. for (int i = 1 % numPoints, n = 0; i != n; i = (i + 1) % numPoints) { if (!support.Contains(i, permuted, mEpsilon)) { if (!Contains(*permuted[i], minimal, distDiff)) { UpdateFunction update = mUpdate[support.Quantity]; Circle2<Real> circle =(this->*update)(i, permuted, support); if (circle.Radius > minimal.Radius) { minimal = circle; n = i; } } } } delete1(permuted); } else { assertion(false, "Input must contain points\n"); } minimal.Radius = Math<Real>::Sqrt(minimal.Radius); }
MinCircle2<Real>::MinCircle2 ( int numPoints, const Vector2<Real>* points, Circle2<Real>& minimal, Real epsilon ) : mEpsilon( epsilon ) { mUpdate[0] = 0; mUpdate[1] = &MinCircle2<Real>::UpdateSupport1; mUpdate[2] = &MinCircle2<Real>::UpdateSupport2; mUpdate[3] = &MinCircle2<Real>::UpdateSupport3; Support support; Real distDiff; if ( numPoints >= 1 ) { // Create identity permutation (0,1,...,numPoints-1). Vector2<Real>** permuted = new1<Vector2<Real>*>( numPoints ); int i; for ( i = 0; i < numPoints; ++i ) { permuted[i] = ( Vector2<Real>* )&points[i]; } // Generate random permutation. for ( i = numPoints - 1; i > 0; --i ) { int j = rand() % ( i + 1 ); if ( j != i ) { Vector2<Real>* save = permuted[i]; permuted[i] = permuted[j]; permuted[j] = save; } } minimal = ExactCircle1( *permuted[0] ); support.Quantity = 1; support.Index[0] = 0; i = 1; while ( i < numPoints ) { if ( !support.Contains( i, permuted, mEpsilon ) ) { if ( !Contains( *permuted[i], minimal, distDiff ) ) { UpdateFunction update = mUpdate[support.Quantity]; Circle2<Real> circle = ( this->*update )( i, permuted, support ); if ( circle.Radius > minimal.Radius ) { minimal = circle; i = 0; continue; } } } ++i; } delete1( permuted ); } else { assertion( false, "Input must contain points\n" ); } minimal.Radius = Math<Real>::Sqrt( minimal.Radius ); }